点击时展开/折叠行,嵌套数据网格

时间:2019-07-04 13:33:47

标签: c# wpf datagrid

我有一个带有三个嵌套数据网格的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>();
}

0 个答案:

没有答案