【问题标题】:WPF row height binding stops working after user uses GridSplitter用户使用 GridSplitter 后 WPF 行高绑定停止工作
【发布时间】: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。有谁知道问题出在哪里?

感谢您的帮助。

【问题讨论】:

    标签: c# wpf binding grid height


    【解决方案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 而不是字符串,我会先尝试。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-11-23
          • 2015-07-30
          • 2011-04-23
          相关资源
          最近更新 更多