在WPF DataGrid中显示层级父子数据

5

我需要能够在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区域。
另一个使用多个网格的副作用是,如果我使用鼠标选择行,我可以得到多个“选定”行效果,即选择了一个父项和其他已在内部网格中先前选择的其他父项的子记录仍然看起来突出显示。
有人能给我任何指针,如何解决这些问题吗?
这里是XAML中引用的visibilityConverter的代码;
 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;
    }
}

副作用:侵入DataGrid的SelectedCellsChanged和/或SelectionChanged事件;当触发时,使用EventArgs取消选择先前的子单元格。 - Jake Berger
我正在努力弄清楚如何获取先前选择的子单元格,有什么线索吗?我对WPF还不太熟悉,谢谢。 - Mark D
当选择任何单元格时,应该触发事件;因此,将单元格存储在本地变量中(例如,List<DataGridCell> selectedCells;); 然后当事件被触发时,检查本地变量以查看是否有任何单元格被选中,并进行取消选中操作;然后将新选定的单元格存储到本地变量中。 - Jake Berger
不要在另一个数据网格内使用数据网格。我从来没有见过有好的理由这样做。使用数据模板来模拟子行的网格布局。 - NVM
谢谢NVM,如果我使用一个模仿子项网格布局的数据模板,我是否仍然会遇到导航问题? - Mark D
1个回答

0

我也有同样的需求。我已经按照以下方式实现了条件。当展开器打开时,您可以使用以下代码。

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。该代码帮助重置所选项,每当展开器打开时。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接