2015-05-06 2 views
0

Мне нужно реализовать окно, содержащее несколько таблиц, в один просмотр прокрутки. Это означает, что эти таблицы должны быть растянуты по содержимому. Пользователь может добавлять/удалять элементы (строки) в эти таблицы.WPF: Быстрая автоматическая калибровка по высоте сетки

Концепция была показана на следующем макете. Основная проблема заключается в том, что сетка не должна иметь полосу прокрутки, она должна иметь динамическую высоту.

enter image description here

На данный момент этот интерфейс реализуется как ItemsControl внутри ScrollViewer. В ItemTemplate элемента ItemsControl добавлен 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: заменил его ItemsControl на 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 или найти один готовый к использованию. Может ли кто-нибудь мне что-нибудь предложить? Может быть, обходной или легкий контроль?

+0

Вы можете добавить некоторые примеры кода, как приложение выглядит на момент? Это значительно облегчает объяснение, почему происходят определенные вещи, и каким образом вы должны их менять. На данный момент трудно дать вам хорошие предложения, не догадываясь – Domysee

+0

См. Мой обновленный ответ ниже .... Возможно, вы захотите рассмотреть вопрос о настройке Grid.RowDefinition на Height = «Auto». – phillk6751

ответ

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> 

Вот Main 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; } 

и вот что "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> 
+0

Я знаю, как его реализовать. Проблема только в производительности. Сетки с динамической высотой очень медленные. В моем случае есть несколько сеток на экране одновременно. –

Смежные вопросы