用户使用 GridSplitter 后 WPF 行高绑定停止工作

Posted

技术标签:

【中文标题】用户使用 GridSplitter 后 WPF 行高绑定停止工作【英文标题】:WPF row height binding stops working after user uses GridSplitter 【发布时间】:2013-12-06 02:41:40 【问题描述】:

我有一个四行网格:

<Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>                
            <RowDefinition Height="Binding DocumentsHeight"/>
            <RowDefinition Height="Auto"/> - GRIDSPLITTER
            <RowDefinition Height="Binding ApprovedDocumentsHeight" /> 
</Grid.RowDefinitions>

行的动态调整大小可以正常工作,高度绑定到具有“5*”等值的字符串。但是当用户使用 GridSplitter 时,绑定停止工作,当我想更改行的大小时,在下一次通知后不会调用 getter。有谁知道问题出在哪里?

感谢您的帮助。

【问题讨论】:

【参考方案1】:

如果网格宽度或高度绑定到 ViewModel(实现 INPC)中的 GridLength 属性,则正确的转换器是:

public class GridLengthConverter : IValueConverter

    public object Convert(object value, Type targetType, object parameter,
        CultureInfo culture) => value;

    public object ConvertBack(object value, Type targetType, object parameter,
        CultureInfo culture) => value;

在视图中绑定是这样的(这里是行高,但它可以是另一个属性):

<RowDefinition Height="Binding TopLength, Mode=TwoWay,
    Converter=StaticResource GridLengthConverter"/>

在资源字典中,converters 将映射到类GridLengthConverter 所在的命名空间:

<converters:GridLengthConverter x:Key="GridLengthConverter" />

【讨论】:

【参考方案2】:

可重复使用的解决方案是使用转换器...

public class DoubleToGridLengthConverter : IValueConverter

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    
        if (value is double len)
            return new GridLength(len, GridUnitType.Pixel);
        return new GridLength(0, GridUnitType.Auto);
    

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    
        return value is GridLength ? ((GridLength)value).Value : 0;
    

【讨论】:

【参考方案3】:

如果您绑定到除 GridLength 之外的任何内容,则绑定将中断。 您可以像这样绑定到 GridLength 属性...

   private double documentsHeight = 100;

   public GridLength DocumentsHeight
    
        get  return this.GridLength(this.documentsHeight); 
        set  this.documentsHeight = value.Value; 
    

您还需要在绑定上设置 Mode=TwoWay。

【讨论】:

完全正确。您也可以使用 IValueConverter 在 double 和 GridLength 之间进行转换。【参考方案4】:

所以我通过将绑定设置为具有双向模式的 GridLength 属性来使其工作。这样,网格拆分器会正确设置值并且绑定不会中断。

【讨论】:

【参考方案5】:

为了发挥它的魔力,拆分器通过将 Height 属性设置为显式值来调整其上方行的高度。这会导致调用 SetValue,从而从属性中删除绑定。您必须手动恢复绑定以使用更改通知来更新行大小,但如果您这样做,那么您可能只想考虑直接设置高度而不是使用绑定。或者,您可以创建自己的拆分器,在 Height 属性上使用 SetCurrentValue,这不会覆盖现有绑定。

【讨论】:

所以我通过将绑定设置为具有双向模式的 GridLength 属性来使其工作。这样,网格拆分器会正确设置值并且绑定不会中断。 在gridsplitter后代中,如何调用SetCurrentValue并防止SetValue被调用? 不要做 gridsplitter 后代,做一个替换控件。【参考方案6】:

可能有很多东西。拆分器必须“接管”行/列定义才能更改宽度/高度。这可能会导致绑定被删除。探索代码并确切了解发生了什么需要一些时间,但这毫无意义,因为我们已经知道它会失败。

因此,您可能无法轻松地做您想做的事。如果是我,我会通过将其包装在 UserControl 中来表达我想要的功能。在 DocumentsHeightApprovedDocumentsHeight 的 UserControl 上公开 DependencyProperties。我会将change event handlers 添加到这些属性中,然后从控件的代码隐藏中适当地调整拆分器位置。

【讨论】:

我刚刚发现它可能有效,如果我绑定到 GridLength 而不是字符串,我会先尝试。

以上是关于用户使用 GridSplitter 后 WPF 行高绑定停止工作的主要内容,如果未能解决你的问题,请参考以下文章

wpf中的grid使用分割器GridSplitter 为啥拉不动

WPF Demo13 GridSplitter

C#/WPF Grid和GridSplitter布局问题。

WPF GridSplitter Column Width="Auto" 时的奇怪行为

WPF如何使曲面带网格

WPF如何使曲面带网格