我需要能够在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;
}
}