繁体   English   中英

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

[英]WPF: Fast auto-sizing by height grid

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

以下模型显示了该概念。 主要问题是网格不应具有滚动条,而应具有动态高度。

在此处输入图片说明

目前,此接口已在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个项目,应用程序不可能变得很慢:渲染它需要几分钟。 分析后,我发现几乎所有时间都花在Measure和Arrange方法上。 我还发现,建议不要将DataGrid用作约束对象,以无限的方式对其进行度量。 因此我无法理解问题,但是无法更改界面。

我尝试编写不带DataGrid的相同接口:用TextBlocks将其替换为ItemsControl。 此解决方案工作正常。 但是我有几个相似的接口,编写这么多相似的代码看起来不太好。 下面显示的代码替代了先前示例中的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或找到一个可以使用的控件。 有人可以建议我吗? 也许一些解决方法或轻量级控制?

重新回答我。...这是您问题的更好解决方案。 我确定您可以弄清楚如何对其进行修改以使其起作用:

在我的主窗口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>

例如,以下是主窗口(testVM)的主ViewModel,这些视图都是在构造函数中完成的:

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

这就是“ itemTypeA”的样子:

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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM