WPF 绑定到网格列宽

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/285730/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 19:47:21  来源:igfitidea点击:

WPF Binding to Grid Column Width

wpfgrid

提问by Ash

I'm attempting to bind a DependancyPropertyin one of my usercontrols to the Widthproperty of a Columnin a Grid.

我试图将DependancyProperty我的一个用户控件中的a 绑定到WidthaColumn中的 a的属性Grid

I have code similar to this:

我有类似的代码:

<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>

In a separate Usercontrol I have the followingDependancyPropertydefined.

在单独的用户控件中,我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); }
}

I am creating instances of the Usercontrol in code, hence I have a binding statement similar to this :

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

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 */

The first binding defined works fantastically, although that is binding to an actual UIElement (in this case a Slider), but the Binding to "TitleSection" (which is the ColumnDefinition defined in the Grid) fails. Putting a breakpoint in the code and doing a watch on "TitleSection" returns the expected object.

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

I am beginning to suspect that a x:Name'd ColumnDefinition can't be bound to. Can anyone suggest how I might be able to bind to the changing width of the first column in my grid?

我开始怀疑 ax:Name'd ColumnDefinition 不能绑定到。任何人都可以建议我如何能够绑定到网格中第一列不断​​变化的宽度?

EDIT #1 - To answer comments

编辑 #1 - 回答评论

The databinding 'fails' in the sense that with a breakpoint set on the setter for the TitleWidthproperty, and using the GridSplitter control to resize the first column, the breakpoint is never hit. Additionally, code I would expect to be fired when the DependancyProperty TitleWidthchanges does not get executed.

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

The usercontrol is being created and added to a Stackpanel within the Grid in the Window_Loadedfunction. I would expect that the Grid has been rendered by the time the Usercontrols are being constructed. Certainly the x:Name'd Element TitleSectionis watchable and has a value of 100when they are being constructed / before the binding is happening.

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

EDIT #2 - Possibly something to do with this?

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

I've been having a sniff round the MSDN pages for the Grid ColumnDefinition documentation and have come across GridLength()but I can't get my head around how I can use this in a binding expression. I cannot use the associated GridLengthConverter as a converter in the binding code as it does not derive from IValueConverter.

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

I am leaning towards somehow binding to the ActualWidth property of one of the cells in the Grid object. It doesn't seem as clean as binding to the column definition, but at the moment I cannot get that to work.

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

回答by Ash

Well I have got a bit of a kludge working, I'll explain how for future generations:

好吧,我有一些杂乱无章的工作,我将向后代解释如何:

Essentially I have a 2 column, multi row grid with a splitter right aligned in the first column so it can be resized by the user if the content it contains requires more space. To complicate things I have a user control being loaded programatically into some of the rows which has a columnSpan of 2 for rendering purposes (content 'bleeds' from one cell into the next).

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

When the first column is resized I need this to be reflected in the usercontrol. Firstly I tried binding to the ColumnDefinition but it really wasn't playing ball.

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

How I fixed/Kludged it

我是如何修复/混合它的

In a spare cell in the first column I added a <Label>with an x:Name to make it accessible. As it is in a cell it has default properties of 'Stretch' and fills the cell completely. It gets resized as the column is resized using the splitter. Binding to the Label's ActualWidthproperty means that changes to the size of the column are communicated to the DependancyProperty in my columnSpanned usercontrol correctly.

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

Thoughts

想法

Obviously, despite ColumnDefinition having an ActualWidthproperty when it changes it doesn't appear to fire the PropertyChangedevent internally (or thats my best guess). This may be a bug, or by design, but for me it means I've had to use a less clean solution.

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

回答by Ian Oakes

Have you tried setting up the binding in xaml, the following should work for you.

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

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

Otherwise, looking at the binding code you've supplied, it looks the wrong way around to me, the target of the binding should be the grid column and the source should be your dependency property.

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

The equivalent code for the above xaml is

上述 xaml 的等效代码是

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

On a related note, using a GridSplitter and binding the Width property are mutally exclusive. As soon as you resize the column using the splitter, your binding will be replaced with the value from the splitter.

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

This is similar to what you would experience by updating any property that is the target of a binding. When you set the targets value directly in code, you are esentially replacing the binding object with the value you supply.

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

回答by JCH2k

ColumnDefinition.Width is not an integer - it is a GridLength. You can't bind the GridLength directly to the Integer, you need a converter.

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

This is also the reason, why you can't bind any Control's Width property (double) to a ColumnDefinition's Width property (GridLength) without a converter.

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