【问题标题】:how to set heights of 3 DataGrids inside Extenders in one StackPanel in MVVM dynamically?如何在 MVVM 的一个 StackPanel 中动态设置扩展器内的 3 个 DataGrid 的高度?
【发布时间】:2015-04-25 03:22:53
【问题描述】:

每个 DataGrid 的高度应该取决于:

  1. 是否扩展了其他扩展器
  2. DataGrid 有多少行
  3. 如果扩展了其他 Extender,其他 DataGrid 有多少行。
  4. 扩展器所在的 StackPanel 的高度

所有扩展程序都应该始终可见。

如果例如只打开最上面的 Extender 并且它的 DataGrid 有 100 行 DataGrid 的高度应该几乎是 StackPanel 的高度,但在底部其他两个 Extender 应该是可见的并且最上面的 DataGrid 是可滚动的。

当打开 2 或 3 个扩展器时,如果 DataGrids 中有足够的数据,则 StackPanel 应该是“满的”。

我尝试绑定高度属性(用于最下方的扩展器对象信息)

    <Expander Header="Object information" IsExpanded="{Binding ObjectInformationExpanded}">
        <DataGrid Name="ObjectInformationGrid" CanUserAddRows="False" CanUserResizeColumns="True" CanUserSortColumns="True" IsReadOnly="True" 
               ItemsSource="{Binding SelectedObjectAttributes}" AutoGenerateColumns="False" 
                  Height="{Binding ObjectInformationHeight, Mode=TwoWay}"
                  ScrollViewer.CanContentScroll="True"
                  ScrollViewer.VerticalScrollBarVisibility="Visible">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Field" Binding="{Binding Item1}" />
                <DataGridTextColumn Header="Value" Binding="{Binding Item2}" />
            </DataGrid.Columns>
        </DataGrid>
</Expander>

但是现在我的 ViewModel 有很多与演示(视图)相关的代码,并且仍然没有将 StackPanel 的高度纳入计算。相反,我设置了硬编码的双精度值,这不是很好的解决方案。

下面是一些简单的代码,当扩展器打开/关闭并且 DataGrid 绑定集合发生更改时更新绑定高度属性(此处仅适用于最上面的 DataGrid):

   private void UpdateHeights()
   {
        if (SelectedObjectsExpanded == true)
        {
            if (_selectedObjects.Count == 0)
            {
                SelectedObjectsHeight = double.NaN;
            }
            else if (_selectedObjects.Count < 8)
            {
                SelectedObjectsHeight = 100;
            }
            else
            {
                if (ObjectInformationExpanded && SelectedSwitchesExpanded)
                    SelectedObjectsHeight = 100;
                else
                    SelectedObjectsHeight = 200;
            }
        }
        //...

谢谢!

【问题讨论】:

    标签: wpf mvvm data-binding datagrid


    【解决方案1】:

    this 这样的东西会起作用吗?

    基本思路是将所有3个Expanders放在一个包含3行的Grid中,并将每一行的RowDefinition.Height绑定到Expander.IsExpanded。如果展开器折叠(仅占用所需空间),则使用转换器将值设置为Auto,或者如果展开器(占用所有剩余空间)则设置为*。如果将多行设置为* 高度,在它们之间平均共享空间)。

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="{Binding IsExpanded, ElementName=Expander1, Converter={x:Static MyBoolToGridSizeConverter}}" />
            <RowDefinition Height="{Binding IsExpanded, ElementName=Expander2, Converter={x:Static MyBoolToGridSizeConverter}}" />
            <RowDefinition Height="{Binding IsExpanded, ElementName=Expander3, Converter={x:Static MyBoolToGridSizeConverter}}" />
        </Grid.RowDefinitions>
    
        <Expander Grid.Row="0" x:Name="Expander1">
            <DataGrid />
        </Expander>
        <Expander Grid.Row="1" x:Name="Expander2">
            <DataGrid />
        </Expander>
        <Expander Grid.Row="2" x:Name="Expander3">
            <DataGrid />
        </Expander>
    </Grid>
    
    public class BoolToGridSizeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            if (value is bool && (bool)value)
                return new GridLength(1, GridUnitType.Star);
    
            return GridLength.Auto;
        }
    
        public object ConvertBack(object value, Type targetType, 
            object parameter, CultureInfo culture)
        {
            // this is not needed
        }
    }
    

    【讨论】:

    • 听起来更好,而不是使用StackPanel。但是,我猜DataGrids 的ScrollViewers 不会出现,因为网格有无限的高度?
    • 感谢您的回答@Rachel!我在晚上(几个小时)评估这个。如果@Herdo 的担忧是有道理的,请在有时间的情况下重复您的答案。
    • @Herdo 我忘记了扩展器是否限制其子级的大小,但如果这是一个问题,您可以轻松地将 DataGrid 的高度绑定到扩展器的高度。或者您可以尝试将它们包装在一个限制高度的面板中,例如Grid。您也可以将它们包装在 ScrollViewer 中,但这会禁用 DataGrid 的虚拟化,因此我不建议您这样做,除非您事先知道您的 Grid 不会有很多数据。
    • @Rachel:这行得通!滚动条也是可见的。所以当我阅读我的问题时,我会说答案是完美的,我会接受它。但是,当数据网格为空时打开扩展器的数据网格时,扩展器会占用整个区域。高度是否也可以以某种方式绑定到 DataGrid 的高度?
    • @matti 您必须切换到MultiValueConverter 才能将多个值传递给转换器,并为每个DataGrid 绑定项目计数。那么如果是Expander.IsExpanded = falseItemCount = 0,则使用GridSize.Auto
    猜你喜欢
    • 1970-01-01
    • 2017-06-15
    • 2017-12-06
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多