У меня есть сетка данных WPF с тремя вложенными сетками данных. Когда пользователь щелкает строку, она должна развернуться, чтобы показать следующий уровень, если он не развернут, а затем свернуть его.
Я пытался захватить событие PreviewMouseLeftButtonDown для DataGridRow, но событие срабатывает для каждой вложенной сетки данных, когда они раскрываются (т. Е. Если я нажимаю на третьем уровне, событие запускается трижды), и я не могу различать их (IsMouseOver и т. д. верно для всех отправителей событий).
Есть ли способ заставить событие срабатывать только для затронутой строки? Или какой-то более простой способ сделать это?
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>();
}