WPF:通过高度网格快速自动调整大小

时间:2015-05-06 15:22:50

标签: wpf datagrid autosize

我必须将包含多个表的窗口实现到一个滚动查看器中。这意味着这些表应该由内容拉伸。用户可以在这些表中添加/删除项目(行)。

这个概念在以下模型中显示。主要问题是网格不应该有滚动条,它应该有动态高度。

enter image description here

目前,此接口在ScrollViewer中实现为ItemsControl。在ItemsControl的ItemTemplate中添加了DataGrid来表示表格数据。

<ScrollViewer CanContentScroll="True"
              HorizontalScrollBarVisibility="Auto">

    <ItemsControl ItemsSource="{Binding Path=Groups}"
                  VirtualizingStackPanel.IsVirtualizing="True">

        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel Orientation="Vertical" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>

        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="125" />
                        <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>

                    <Label Grid.Column="0" Grid.Row="0"
                           Style="{StaticResource ResourceKey=LabelBaseStyle}"
                           Content="{Binding Path=GroupLabel}"
                           HorizontalAlignment="Right"/>

                    <Button Content="{x:Static Member=Resources:CommonStrings.Delete}"
                            Style="{StaticResource ResourceKey=ButtonBaseStyle}"
                            VerticalAlignment="Center" />

                    <DataGrid Grid.Row="0" Grid.Column="1"
                              AutoGenerateColumns="False"
                              ItemsSource="{Binding Path=Items}">
                        <DataGrid.Columns>
                        <!-- 21 text columns here -->
                        </DataGrid.Columns>
                    </DataGrid>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

</ScrollViewer>

此解决方案可以正常工作,直到添加了一些数据。现在在7个表(网格)上,每个应用程序中大约有50个项目,应用程序不可能很慢:渲染它需要几分钟。在分析后,我发现几乎所有的时间都花在了测量和排列方法上。此外,我发现重新贴合不要将DataGrid用于使用无穷大测量它的对手。所以我没有解决问题,但我不能改变界面。

我试图在没有DataGrid的情况下编写相同的接口:用ItemsBtrol替换TextBlocks。此解决方案工作正常。但是我有几个类似的接口,编写这么多相似的代码并不是很好。下面显示的代码是上一个示例中DataGrid的替代:

<ItemsControl ItemsSource="{Binding Path=Items}"
          VirtualizingStackPanel.IsVirtualizing="True"
          Grid.Row="0" Grid.Column="1">

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel Orientation="Vertical" />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Path=Type}" />
            <!-- Another 20 TextBlocks here -->
        </StackPanel>
    </DataTemplate>
</ItemsControl.ItemTemplate>

所以我需要实现自己的UserControl或找到一个可以使用的。 谁能建议我什么?也许一些解决方法或轻量级控制?

1 个答案:

答案 0 :(得分:0)

重新做了我的回答......这是一个更好的解决方案。我确定你可以弄清楚如何修改它来工作:

在我的主窗口Xaml中:

<ScrollViewer Height="Auto" Width="Auto" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Visible">
    <StackPanel Height="Auto" Width="Auto">
        <ItemsControl ItemsSource="{Binding ItemList}">
            <ItemsControl.Resources>
                <DataTemplate DataType="{x:Type wpfmvvmtest:itemTypeA}">
                    <wpfmvvmtest:testUC></wpfmvvmtest:testUC>
                </DataTemplate>
            </ItemsControl.Resources>
        </ItemsControl>
    </StackPanel>
</ScrollViewer>

这里是主窗口的主ViewModel(testVM),所有这些都在构造函数中完成,例如:

public testVM()
{
    ItemList = new ObservableCollection<object>();
    Random rnd = new Random();

    for (int i = 0; i < 3; i++)
    {
        itemTypeA item = new itemTypeA(rnd.Next(100));

        ItemList.Add(item);
    }
}

public ObservableCollection<object> ItemList { set; get; } 

以及&#34; itemTypeA&#34;就像:

public itemTypeA(int count)
{
    Items = new DataTable();
    Items.Columns.Add("One");
    Items.Columns.Add("Two");
    Items.Columns.Add("Three");
    Items.Columns.Add("Four");

    Description = "Count = " + count;
    for (int i = 0; i < count; i++)
    {
        DataRow dr = Items.NewRow();
        dr[0] = i*1;
        dr[1] = i * 2;
        dr[2] = i * 3;
        dr[3] = i * 4;
        Items.Rows.Add(dr);
    }
}

public DataTable Items { set; get; } 

这里是重要的部分(确保您的UserControl中没有为DataTemplate设置高度/宽度属性(允许DataGrid设置高度/宽度):

<UserControl x:Class="wpfmvvmtest.testUC"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             d:DataContext="d:designInstance itemTypeA"
             mc:Ignorable="d">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" HorizontalAlignment="Stretch" Content="{Binding Description}"></Label>
        <Border Grid.Row="1" BorderBrush="Black" BorderThickness="2">
        <DataGrid ItemsSource="{Binding Path=Items}">
        </DataGrid>
        </Border>
    </Grid>
</UserControl>