Отображение иерархических родительских дочерних данных в WPF DataGrid - PullRequest
1 голос
/ 19 марта 2012

Мне нужно иметь возможность отображать родительские / дочерние строки в сетке данных WPF, родительские элементы отображаются с элементом управления плюс / минус, который при нажатии отображает связанные дочерние записи.

Для этого яобычно размещают вторую сетку данных в родительских сетках RowDetailsTemplate и триггер стиля, чтобы перевернуть свойство detailsvisibility в каждой строке.например,

<Grid>
    <DataGrid AutoGenerateColumns="False" IsReadOnly="True" ItemsSource="source" Margin="10,10,14,14" Name="dataGrid1" RowDetailsVisibilityMode="Collapsed" SelectionMode="Single">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding FullName}" Header="Name" />
            <DataGridTextColumn Binding="{Binding Details}" Header="Details" />
        </DataGrid.Columns>
        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <DataGrid HeadersVisibility="None" AutoGenerateColumns="False" IsReadOnly="True" ItemsSource="{Binding Path=Attachments}">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding Document}" Header="Document" />
                        <DataGridTextColumn Binding="{Binding Created}" Header="Date Created" />
                    </DataGrid.Columns>
                </DataGrid>
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>
        <DataGrid.RowHeaderTemplate>
            <DataTemplate>
                <ToggleButton IsChecked="{Binding Converter={StaticResource visibleConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, Path=DetailsVisibility}">
                    <Image>
                        <Image.Style>
                            <Style TargetType="Image">
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton}, Path=IsChecked}" Value="false">
                                        <Setter Property="Image.Source" Value="Images/plus-8.png" />
                                    </DataTrigger>
                                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton}, Path=IsChecked}" Value="true">
                                        <Setter Property="Image.Source" Value="Images/minus-8.png" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </Image.Style>
                    </Image>
                </ToggleButton>
            </DataTemplate>
        </DataGrid.RowHeaderTemplate>
    </DataGrid>
</Grid>

Проблема 1 в том, что когда я использую клавиатуру для перемещения вверх и вниз по родительской сетке, она пропускает дочернюю сетку, пропуская область RowDetailsTemplate.

Еще один побочный эффект использования несколькихСетки, если я использую мышь для выбора строк, я могу получить эффект нескольких «выделенных» строк, то есть один из родителей выбран, а другие дочерние записи для других родителей, которые ранее были выбраны во внутренних сетках, выглядят так, как будто они все еще подсвечены.

Кто-нибудь может подсказать здесь, как обойти эти проблемы?

Здесь код для видимостиConverter, на который есть ссылка в XAML выше;

 public class VisibleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool visibleValue = false;
        if (value != null && value is Visibility)
        {
            visibleValue = !((Visibility)value == Visibility.Collapsed);
        }
        return visibleValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Visibility visibleValue = Visibility.Collapsed;
        if (value is bool)
        {
            if ((bool)value == true)
            {
                visibleValue = Visibility.Visible;
            }
        }
        return visibleValue;
    }
}

1 Ответ

0 голосов
/ 28 марта 2012

Даже у меня такое же требование.Я выполнил условие следующим образом.Когда расширитель открыт, вы можете иметь следующий код:

private void Expander_Expanded(object sender, RoutedEventArgs e)
{
   foreach (var item in viewModel.Results)
   {
     if (item.SubResults.Count > 0)
      {
        item.SubResults.SelectedItem = null;
      }
   }
}

Где Results - источник элементов для моей внешней сетки, а Subresults - источник данных для моей внутренней сетки.Этот код помогает сбросить выбранный элемент при каждом открытии расширителя.

...