我有一个带有三个嵌套数据网格的WPF数据网格。当用户单击一行时,它应该展开以显示下一个级别,除非它已经被展开,则应该将其折叠。
我尝试捕获DataGridRow的PreviewMouseLeftButtonDown事件,但是当每个嵌套的datagrid展开时都会触发该事件(即,如果我单击第三级,则该事件被触发三次),但是我无法区分它们(IsMouseOver等。对于所有事件发送者都是True)。
是否有一种方法可以使事件仅针对受影响的行触发?还是一些更简单的方法?
XAML:
<Window x:Class="StackOverflowEx.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverflowEx"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Height="450">
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" x:Name="MainGrid" FontWeight="Bold" RowHeight="60" ItemsSource="{Binding FirstLevel}">
<DataGrid.Columns>
<DataGridTextColumn Header="Test" Binding="{Binding Name, FallbackValue='Test'}" />
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridRow_PreviewMouseLeftButtonDown"/>
</Style>
</DataGrid.RowStyle>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" Margin="60, 0, 0, 0" FontWeight="Regular" RowHeight="30" HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding NextLevel}">
<DataGrid.Columns>
<DataGridTextColumn Header="Test" Binding="{Binding Name, FallbackValue='Test'}" />
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridRow_PreviewMouseLeftButtonDown" />
</Style>
</DataGrid.RowStyle>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" Margin="60, 0, 0, 0" FontWeight="Regular" RowHeight="30" HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding NextLevel}">
<DataGrid.Columns>
<DataGridTextColumn Header="Test" Binding="{Binding Name, FallbackValue='Test'}" />
</DataGrid.Columns>
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridRow_PreviewMouseLeftButtonDown" />
</Style>
</DataGrid.RowStyle>
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid CanUserAddRows="False" AutoGenerateColumns="False" Margin="40, 0, 0, 0" RowHeight="20" FontWeight="Regular" HorizontalScrollBarVisibility="Disabled" ColumnWidth="60" ItemsSource="{Binding NextLevel}">
<DataGrid.Columns>
<DataGridTextColumn Header="Test" Binding="{Binding Name, FallbackValue='Test'}" />
</DataGrid.Columns>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
</Window>
后面的代码:
public partial class MainWindow : Window, INotifyPropertyChanged
{
private ObservableCollection<DataClass> firstLevel = new ObservableCollection<DataClass>();
private ObservableCollection<DataClass> secondLevel = new ObservableCollection<DataClass>();
private ObservableCollection<DataClass> thirdLevel = new ObservableCollection<DataClass>();
private ObservableCollection<DataClass> fourthLevel = new ObservableCollection<DataClass>();
public ObservableCollection<DataClass> FirstLevel
{
get => firstLevel; set
{
firstLevel = value;
NotifyPropertyChanged();
}
}
public ObservableCollection<DataClass> SecondLevel
{
get => secondLevel; set
{
secondLevel = value;
NotifyPropertyChanged();
}
}
public ObservableCollection<DataClass> ThirdLevel
{
get => thirdLevel; set
{
thirdLevel = value;
NotifyPropertyChanged();
}
}
public ObservableCollection<DataClass> FourthLevel
{
get => fourthLevel; set
{
fourthLevel = value;
NotifyPropertyChanged();
}
}
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
FourthLevel.Add(new DataClass { Name = "Fourth" });
ThirdLevel.Add(new DataClass { Name = "Third" });
ThirdLevel.Last().NextLevel = FourthLevel;
SecondLevel.Add(new DataClass { Name = "Second" });
SecondLevel.Last().NextLevel = ThirdLevel;
FirstLevel.Add(new DataClass { Name = "First" });
FirstLevel.Last().NextLevel = SecondLevel;
}
public event PropertyChangedEventHandler PropertyChanged;
private void DataGridRow_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DataGridRow row = sender as DataGridRow;
if (row != null)
{
row.DetailsVisibility = row.DetailsVisibility == Visibility.Visible ? System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
}
}
}
public class DataClass : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public string Name { get; set; }
public ObservableCollection<DataClass> NextLevel { get; set; } = new ObservableCollection<DataClass>();
}