Как установить фокус на Expander в DataGrid при выборе строки с помощью мыши? - PullRequest
0 голосов
/ 13 марта 2020

Я новичок в WPF и C#. Я играю с DataGrid, который содержит некоторую базовую c информацию из класса Person.

public class Person
{
    public string Name { get; set; }
    public string Number { get; set; }
    public string Email { get; set; }
    public string Data { get; set; }

    public Person()
    { }
}

Я использую этот класс для заполнения DataGrid. В качестве части сетки данных у меня есть расширитель, который отображает детализацию строк и показывает свойство «Данные» объектов Person.

Проблема, с которой я сталкиваюсь, заключается в том, что я получаю различные варианты поведения с фокусом в зависимости от как я вхожу в решетку. Когда я щелкаю мышью по сетке, строка выделяется, но расширитель не получает фокус, что я и хочу. Таким образом, я могу нажать клавишу наподобие пробела и переключить расширитель.

Mouse Selected Row. No focus on the Expander

После выбора строки, если я нажму клавишу со стрелкой, она установит фокус на расширитель.

Когда я вкладываю в сетку, расширитель получает фокус и выделяется строка. Теперь я могу нажать клавишу, например пробел , и расширитель переключается.

Я также замечаю, что когда я вкладываю в сетку первую ячейку первого ряда, она фокусируется, но не выбранный, если в сетке уже был предыдущий выбор.

Tab focus in DataGrid with previous row selected

Я пробовал много вещей, которые я искал в Интернете, но ни один кажется, что они выполнили sh того, что я пытаюсь сделать.

Я пытался захватить различные события мыши и выбора и пройтись по визуальному дереву, пока не нашел расширитель и не установил фокус, но это не не работает Я попытался установить расширитель в качестве выбранного selectedAnchor, еще раз он не сработал.

Мне кажется, что я здесь упускаю довольно простой шаг. Буду признателен за любую помощь.

Xaml:

        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:DataGridExample"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="400">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <DataGrid Name="PersonGrid" HorizontalAlignment="Center" Margin="4" VerticalAlignment="Center"
                  RowDetailsVisibilityMode="Collapsed"
                  CanUserResizeRows="False"
                  SelectionUnit="FullRow"
                  GridLinesVisibility="None"
                  HeadersVisibility="Column"
                  IsReadOnly="True"
                  KeyboardNavigation.TabNavigation="Once"
                  AutoGeneratingColumn="PersonGrid_AutoGeneratingColumn"
                  MouseUp="PersonGrid_MouseUp" >
            <DataGrid.Resources>
                <DataTemplate x:Key="ExpandDetails">
                    <Expander x:Name="ShowData" Expanded="Expander_Process" Collapsed="Expander_Process"/>
                </DataTemplate>
                    <Style TargetType="{x:Type DataGridCell}">
                        <Style.Setters>
                            <Setter Property="KeyboardNavigation.IsTabStop" Value="False" />
                            <Setter Property="IsTabStop" Value="False"/>                            
                        </Style.Setters>
                        <Style.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter Property="Focusable" Value="false"/>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTemplateColumn x:Name="DataExpander" Header="" CellTemplate="{StaticResource ExpandDetails}"
                                        CanUserResize="False" CanUserReorder="False" CanUserSort="False" />
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <Border BorderThickness="0" Background="Bisque" Padding="5">
                        <StackPanel>
                            <TextBlock Text="Additional Data:"/>
                            <TextBox Text="{Binding Path=Data, Mode=OneTime}" Background="Transparent" BorderThickness="0" IsReadOnly="True" TextWrapping="Wrap"  />
                        </StackPanel>
                    </Border>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
        <Button Name="NoPurpose" Content="Push Me"/>
        </StackPanel>
    </Grid>
</Window>

Код:

    {
        public DataGridCellInfo? SelectionAnchor
        {
            get
            {
                return typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(PersonGrid) as DataGridCellInfo?;
            }
            private set
            {
                typeof(DataGrid).GetField("_selectionAnchor", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(PersonGrid, value);
            }
        }

        private List<Person> LoadCollectionData()
        {
            List<Person> people = new List<Person>();
            people.Add(new Person()
            {
                Name = "Billy Joel",
                Number = "555-309-2211",
                Email = "bjoel@anywhere.com",
                Data = "Billy Loves long walks on the beach."
            });

            people.Add(new Person()
            {
                Name = "John Doe",
                Number = "831-312-3213",
                Email = "jdoes@morgue.com",
                Data = "Who are you, who who. I really want to know"
            });

            return people;
        }
        public MainWindow()
        {
            InitializeComponent();
            PersonGrid.ItemsSource = LoadCollectionData();
        }

        private void PersonGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (e.PropertyName == "Data")
            {
                e.Cancel = true;
            }
        }

        private void Expander_Process(object sender, RoutedEventArgs e)
        {
            if (sender is Expander expander)
            {
                var row = DataGridRow.GetRowContainingElement(expander);

                row.DetailsVisibility = expander.IsExpanded ? Visibility.Visible
                                                            : Visibility.Collapsed;
            }
        }

        private childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
        {
            for(int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child is childItem) return (childItem)child;
                childItem childofChild = FindVisualChild<childItem>(child);
                if (childofChild != null) return childofChild;
            }
            return null;
        }
        private void PersonGrid_MouseUp(object sender, MouseButtonEventArgs e)
        {
            PersonGrid.Focusable = true;
            PersonGrid.Focus();
            if (sender is DataGrid dataGrid)
            {
                int index = dataGrid.SelectedIndex;
                if (index < 0)
                    index = 0;

                object item = dataGrid.Items[index];

                if (!(dataGrid.ItemContainerGenerator.ContainerFromIndex(index) is DataGridRow row))
                {
                    dataGrid.ScrollIntoView(item);
                    row = dataGrid.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
                }
                var expander = FindVisualChild<Expander>(row);
                if (expander != null)
                {
                    expander.UpdateLayout();
                    expander.Focusable = true;
                    expander.Focus();
                }

                SelectionAnchor = dataGrid.SelectedCells[0];
            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...