WPF绑定到网格列宽度

时间:2008-11-12 23:04:24

标签: wpf grid

我正在尝试将我的一个用户控件中的DependancyProperty绑定到WidthColumn的{​​{1}}属性。

我的代码类似于:

Grid

在单独的Usercontrol中,我定义了以下<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

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

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); }
}

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

我开始怀疑x:Name'd ColumnDefinition无法绑定。 任何人都可以建议我如何绑定到网格中第一列的宽度变化?

编辑#1 - 回答评论

数据绑定'失败'意味着在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 */ 属性的setter上设置断点,并使用GridSplitter控件调整第一列的大小,断点永远不会被命中。此外,当DependancyProperty TitleWidth更改未执行时,我希望代码被触发。

正在创建usercontrol并将其添加到TitleWidth函数中Grid中的Stackpanel。我希望在构建Usercontrols时渲染Grid。当然,x:Name'd元素Window_Loaded是可观察的,并且在构造它们/发生绑定之前具有值TitleSection

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

我一直在围绕Grid ColumnDefinition文档的MSDN页面进行嗅探,并遇到了GridLength(),但我无法理解如何在绑定表达式中使用它。我不能在绑定代码中使用关联的GridLengthConverter作为转换器,因为它不是从IValueConverter派生的。

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

3 个答案:

答案 0 :(得分:11)

嗯,我有一点工作,我会解释为后代如何:

基本上我有一个2列,多行网格,在第一列中右对齐,因此如果用户包含的内容需要更多空间,则可以由用户调整大小。为了使事情变得复杂,我将用户控件以编程方式加载到某些行中,其中columnSpan为2用于渲染目的(内容'从一个单元格流入下一个单元格)。

调整第一列的大小时,我需要将其反映在usercontrol中。首先,我尝试绑定到ColumnDefinition,但它确实没有打球。

我如何修复/克服

在第一列的备用单元格中,我添加了一个带有x:Name的<Label>以使其可访问。由于它在单元格中具有默认属性“拉伸”并完全填充单元格。当使用拆分器调整列大小时,它会调整大小。绑定到Label的ActualWidth属性意味着对列大小的更改将正确地传递给columnSpanned usercontrol中的DependancyProperty。

<强>思想

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

答案 1 :(得分:3)

您是否尝试过在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属性是互斥的。只要使用拆分器调整列的大小,绑定将替换为拆分器中的值。

这类似于更新作为绑定目标的任何属性的体验。直接在代码中设置目标值时,您实际上是用您提供的值替换绑定对象。

答案 2 :(得分:2)

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

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