【问题标题】:WPF Binding to Grid Column WidthWPF 绑定到网格列宽
【发布时间】:2010-09-22 02:13:51
【问题描述】:

我试图将我的一个用户控件中的DependancyProperty 绑定到Grid 中Column 的Width 属性。

我有类似这样的代码:

<Grid x:Name="MyGridName">
    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="TitleSection" Width="100" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>...</Grid.RowDefinitions>

    <GridSplitter x:Name="MyGridSplitter" Grid.Row="0" Grid.Column="0" ... />
</Grid>

在单独的用户控件中,我定义了以下DependancyProperty。

public static readonly DependencyProperty TitleWidthProperty = DependencyProperty.Register("TitleWidth", typeof(int), typeof(MyUserControl));

public int TitleWidth
{
    get { return (int)base.GetValue(TitleWidthProperty); }
    set { base.SetValue(TitleWidthProperty, value); }
}

我正在代码中创建用户控件的实例,因此我有一个类似于此的绑定语句:

MyUserControl Cntrl = new MyUserControl(/* Construction Params */);
BindingOperations.SetBinding(Cntrl , MyUserControl.AnotherProperty, new Binding { ElementName = "objZoomSlider", Path = new PropertyPath("Value"), Mode = BindingMode.OneWay });
BindingOperations.SetBinding(Cntrl , MyUserControl.TitleWidthProperty, new Binding { ElementName = "TitleSection", Path = new PropertyPath("ActualWidth"), Mode = BindingMode.OneWay });
/* Other operations on Cntrl */

定义的第一个绑定非常有效,尽管它绑定到实际的 UIElement(在本例中为 Slider),但绑定到“TitleSection”(即 Grid 中定义的 ColumnDefinition)失败。在代码中放置断点并监视“TitleSection”会返回预期的对象。

我开始怀疑不能绑定 x:Name'd ColumnDefinition。 谁能建议我如何才能绑定到网格中第一列的不断变化的宽度?

编辑 #1 - 回答 cmets

数据绑定“失败”是因为在 TitleWidth 属性的设置器上设置了断点,并使用 GridSplitter 控件调整第一列的大小,断点永远不会被命中。此外,当 DependancyProperty TitleWidth 更改未执行时,我希望触发的代码。

正在创建用户控件并将其添加到Window_Loaded 函数中网格内的堆栈面板。我希望在构建用户控件时已经呈现了网格。当然 x:Name'd 元素 TitleSection 是可观察的,并且在构造它们时/在绑定发生之前具有 100 的值。

编辑 #2 - 可能与此有关?

我一直在浏览 MSDN 页面以获取 Grid ColumnDefinition 文档,并且遇到了GridLength(),但我不知道如何在绑定表达式中使用它。我不能在绑定代码中使用关联的 GridLengthConverter 作为转换器,因为它不是从 IValueConverter 派生的。

我倾向于以某种方式绑定到 Grid 对象中一个单元格的 ActualWidth 属性。它似乎不像绑定到列定义那样干净,但目前我无法让它工作。

【问题讨论】:

  • 如何以及在什么时候创建用户控件失败?网格显示了吗?
  • 您不能依赖在依赖属性的 set/get 中设置断点,因为绑定引擎永远不会使用它们。使用 SetValue(DependencyProperty, value) 设置内部依赖属性

标签: wpf grid


【解决方案1】:

好吧,我有一些工作要做,我会为后代解释一下:

基本上我有一个 2 列、多行网格,在第一列中有一个右对齐的拆分器,因此如果它包含的内容需要更多空间,用户可以调整它的大小。为了使事情复杂化,我有一个用户控件以编程方式加载到一些行中,这些行的 columnSpan 为 2 用于呈现目的(内容从一个单元格“渗入”到下一个单元格)。

当调整第一列的大小时,我需要将其反映在用户控件中。首先,我尝试绑定到 ColumnDefinition,但它确实没有发挥作用。

我是如何修复/组装它的

在第一列的备用单元格中,我添加了带有 x:Name 的 &lt;Label&gt; 以使其可访问。因为它在一个单元格中,所以它具有“拉伸”的默认属性并完全填充单元格。随着使用拆分器调整列的大小,它会调整大小。绑定到标签的ActualWidth 属性意味着对列大小的更改将正确传达给我的 columnSpanned 用户控件中的 DependancyProperty。

想法

显然,尽管 ColumnDefinition 在更改时具有ActualWidth 属性,但它似乎不会在内部触发PropertyChanged 事件(或者这是我的最佳猜测)。这可能是一个错误,也可能是设计使然,但对我来说,这意味着我不得不使用不太干净的解决方案。

【讨论】:

  • 这对我来说效果很好。我有一个小小的转折:
【解决方案2】:

您是否尝试过在 xaml 中设置绑定,以下内容应该适合您。

<ColumnDefinition 
    x:Name="TitleSection" 
    Width="{Binding 
                Path=TitleWidth, 
                RelativeSource={RelativeSource AncestorType=MyUserControl}}" 
    />

否则,查看您提供的绑定代码,对我来说它看起来是错误的,绑定的目标应该是网格列,源应该是您的依赖属性。

上述xaml的等效代码是

BindingOperations.SetBinding(TitleSection, ColumnDefinition.WidthProperty,
    new Binding()
    {
        RelativeSource= new RelativeSource(RelativeSourceMode.FindAncestor, typeof(MyUserControl),1),
        Path = new PropertyPath("TitleWidth"),
    });

在相关说明中,使用 GridSplitter 和绑定 Width 属性是互斥的。使用拆分器调整列大小后,您的绑定将被拆分器中的值替换。

这类似于您通过更新作为绑定目标的任何属性所遇到的情况。当您直接在代码中设置目标值时,您实际上是将绑定对象替换为您提供的值。

【讨论】:

    【解决方案3】:

    ColumnDefinition.Width 不是整数 - 它是 GridLength。 您不能将 GridLength 直接绑定到 Integer,您需要一个转换器。

    这也是为什么不能在没有转换器的情况下将任何 Control 的 Width 属性 (double) 绑定到 ColumnDefinition 的 Width 属性 (GridLength) 的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-24
      • 2010-10-29
      • 1970-01-01
      • 2012-03-07
      • 2017-06-11
      • 2017-12-31
      • 2020-06-25
      • 1970-01-01
      相关资源
      最近更新 更多