WPF Datagrid cyclically moves / selects cells with a specific property

Brand new to WPF, quite convenient with WinForms (which probably makes the transition rougher). I am trying to port some features from an old WinForms project to WPF as a learning experience.

The goal is to find the cell values ​​in the DataGrid matching the row in the TextBox. I found a great example using bindings that will do just that. Basically, the associated code will change the background color of any corresponding DataGridCell to orange. I changed my version a bit, but the functionality should be the same. See the link for code examples, it seems a bit redundant to provide it here. The data populating my DataGrid is data from a DataTable (if that matters).

From there, I want to make the "next" button that will cycle through each of these cells (determined either using the background color or using the custom property DataGridTextSearch.IsTextMatch) and select it. It seems like you could just change the code provided, but I don't know where to start. In my old WinForms project, I saved the DataGridViewCell in the list (after searching for them using the Linq query) and simply added the button behavior to enlarge the specified list and set the current cell. I suspect that a smarter / better way with bindings is possible, and I don't even know how to add these comparable cells to the list, if this is an option.

So, to summarize, I want the button to launch through specific DataGridCells (based on the background or the custom property DataGridTextSearch.IsTextMatch) and selects them.

Thanks in advance.

+5
source share
1 answer

Based on the link you provided in your question, I came up with a solution for this. In my solution, when the DataGridCell matches the line in the TextBox , the Tag property will be set to "1", and then, when the Button is pressed, it will iterate over all the DataGridCells and find the elements with non-zero Tags and, finally, the selected cells will be focused one by one .

Here is a working example that will give you an idea:

Xaml:

 <Window Name="UI"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <StackPanel DataContext="{Binding ElementName=UI}" Grid.Row="0"> <TextBox Name="SearchBox" TextChanged="SearchBox_TextChanged"/> <DataGrid x:Name="grid" m:DataGridTextSearch.SearchValue="{Binding ElementName=SearchBox, Path=Text, UpdateSourceTrigger=PropertyChanged}" ItemsSource="{Binding TestData}" SelectionUnit="Cell"> <DataGrid.Resources> <m:SearchValueConverter x:Key="SearchValueConverter" /> <Style TargetType="{x:Type DataGridCell}"> <Setter Property="m:DataGridTextSearch.IsTextMatch"> <Setter.Value> <MultiBinding Converter="{StaticResource SearchValueConverter}"> <Binding RelativeSource="{RelativeSource Self}" Path="Content.Text" /> <Binding RelativeSource="{RelativeSource Self}" Path="(m:DataGridTextSearch.SearchValue)" /> </MultiBinding> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="m:DataGridTextSearch.IsTextMatch" Value="True"> <Setter Property="Background" Value="Orange" /> <Setter Property="Tag" Value="1" /> </Trigger> </Style.Triggers> </Style> </DataGrid.Resources> </DataGrid> </StackPanel> <Button Grid.Row="1" Click="Button_Click" Content="GoNext"/> </Grid> </Window> 

MainWindow.cs:

 int currentIndex = 0; private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) { currentIndex = 0; } private void Button_Click(object sender, RoutedEventArgs e) { var selectedCells = GetHighLightedCells(); if (selectedCells.Count == 0) return; selectedCells[currentIndex].Focus(); if (currentIndex == selectedCells.Count - 1) currentIndex = 0; else currentIndex++; } 

Ways to get selected cells:

 public List<DataGridCell> GetHighLightedCells() { List<DataGridCell> selectedCells = new List<DataGridCell>(); foreach (DataGridRow rowContainer in GetDataGridRows()) { if (rowContainer != null) { DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer); foreach (var col in grid.Columns) { DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(col.DisplayIndex); if (cell == null) { grid.ScrollIntoView(rowContainer, col); cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(col.DisplayIndex); } if (cell.Tag != null) { selectedCells.Add(cell); } } } } return selectedCells; } public IEnumerable<DataGridRow> GetDataGridRows() { var itemsSource = grid.ItemsSource as IEnumerable; if (null == itemsSource) yield return null; foreach (var item in itemsSource) { var row = grid.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow; if (null != row) yield return row; } } public static T GetVisualChild<T>(Visual parent) where T : Visual { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); child = v as T; if (child == null) { child = GetVisualChild<T>(v); } if (child != null) { break; } } return child; } 
+5
source

Source: https://habr.com/ru/post/1233653/


All Articles