Я новичок в 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.
Проблема, с которой я сталкиваюсь, заключается в том, что я получаю различные варианты поведения с фокусом в зависимости от как я вхожу в решетку. Когда я щелкаю мышью по сетке, строка выделяется, но расширитель не получает фокус, что я и хочу. Таким образом, я могу нажать клавишу наподобие пробела и переключить расширитель.
После выбора строки, если я нажму клавишу со стрелкой, она установит фокус на расширитель.
Когда я вкладываю в сетку, расширитель получает фокус и выделяется строка. Теперь я могу нажать клавишу, например пробел , и расширитель переключается.
Я также замечаю, что когда я вкладываю в сетку первую ячейку первого ряда, она фокусируется, но не выбранный, если в сетке уже был предыдущий выбор.
Я пробовал много вещей, которые я искал в Интернете, но ни один кажется, что они выполнили 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];
}
}
}