Hi Stashy,
try following demo:
XAML:
<Window x:Class="WpfApp1.Window082"
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:Wpf1App082"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
Title="211111_StashyCode-7539" Height="450" Width="800">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<StackPanel>
<DataGrid Name="Employees" Height="200"
AutoGenerateColumns="False"
CanUserAddRows="False"
EnableColumnVirtualization="True"
EnableRowVirtualization="True"
ItemsSource="{Binding EmployeesDataTable}"
SelectionUnit="CellOrRowHeader"
VirtualizingPanel.VirtualizationMode="Recycling"
IsSynchronizedWithCurrentItem="True">
<i:Interaction.Behaviors>
<local:DataGridBehavior/>
</i:Interaction.Behaviors>
<DataGrid.Columns>
<DataGridTextColumn Header="ID" Binding="{Binding ID}"/>
<DataGridTextColumn Width="100"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
<DataGridTextColumn Width="*"/>
</DataGrid.Columns>
</DataGrid>
<Label Content="{Binding Info}"/>
</StackPanel>
</Window>
and code:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace Wpf1App082
{
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
// Load demo data
for (int i = 0; i < 1000; i++) col.Add(new Data() { ID = i, Name = $"Row {i:0000}" });
cvs.Source = col;
}
private CollectionViewSource cvs = new CollectionViewSource();
private ObservableCollection<Data> col = new ObservableCollection<Data>();
public ICollectionView EmployeesDataTable { get => cvs.View; }
private string _searchName;
public string SearchName
{
get => this._searchName;
set
{
this._searchName = value;
SelItems = new ObservableCollection<Data>(col.Where((d) => d.Name.Contains(value)));
IndexOfSelItem = 0;
NextItem();
}
}
private ObservableCollection<Data> SelItems { get; set; }
private int IndexOfSelItem = 0;
DataGrid AssociatedObject = null;
private Window SearchWindow = null;
public void StartSearch(DataGrid dg)
{
if (SearchWindow == null)
{
AssociatedObject = dg;
SearchWindow = new Window() { Title = "Search", Height = 60, Width = 250, DataContext = this };
SearchWindow.Closing += (s, e) => SearchWindow = null;
SearchWindow.PreviewKeyDown += (s, e) => { if (e.Key == Key.F3) NextItem(); };
TextBox tb = new TextBox();
tb.SetBinding(TextBox.TextProperty, new Binding("SearchName") { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, Mode = BindingMode.TwoWay });
SearchWindow.Content = tb;
SearchWindow.Show();
tb.Focus();
}
SearchWindow.Focus();
SearchWindow.WindowState = WindowState.Normal;
// log
Info = $"{DateTime.Now.ToLongTimeString()} StartSearch";
}
public void NextItem()
{
if (AssociatedObject != null && SelItems != null && SelItems.Count > IndexOfSelItem)
{
cvs.View.MoveCurrentTo(SelItems[IndexOfSelItem]);
var current = EmployeesDataTable.CurrentItem;
AssociatedObject.ScrollIntoView(current);
if (IndexOfSelItem++ >= SelItems.Count - 1) IndexOfSelItem = 0;
}
// log
Info = $"{DateTime.Now.ToLongTimeString()} NextItem";
}
private string _info;
public string Info
{
get => this._info;
set { this._info = value; OnPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propName = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
public class Data
{
public int ID { get; set; }
public string Name { get; set; }
}
public class DataGridBehavior : Behavior<DataGrid>
{
protected override void OnAttached()
{
AssociatedObject.PreviewKeyDown += OnPreviewKeyDown;
AssociatedObject.PreviewKeyUp += OnPreviewKeyUp;
}
private void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F3) ((ViewModel)(AssociatedObject.DataContext)).NextItem();
else if (e.Key == Key.LeftCtrl) LeftCtrl = true;
else if (e.Key == Key.F) ((ViewModel)(AssociatedObject.DataContext)).StartSearch(AssociatedObject);
}
private void OnPreviewKeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.LeftCtrl) LeftCtrl = false; }
private bool LeftCtrl = false;
}
}
Result: