question

StashyCode-7539 avatar image
0 Votes"
StashyCode-7539 asked StashyCode-7539 edited

DataGrid Ctrl + F and F3 functionality WPF MVVM

I am building a WPF MVVM application.

I have a DataGrid, like so:

 <DataGrid 
        Name=“Employees” 
        AutoGenerateColumns=“False”         
        CanUserAddRows=“False” 
        EnableColumnVirtualization=“True” 
        EnableRowVirtualization=“True” 
        ItemsSource={Binding EmployeesCollectionView} 
        SelectionUnit=“FullRow”        
        VirtualizingPanel.VirtualizationMode=“Recycling” /> 

I want to implement a Ctrl+F and F3 search (similar like the browser one).

What is the best way to implement that?

windows-wpfdotnet-wpf-xaml
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

1 Answer

PeterFleischer-3316 avatar image
1 Vote"
PeterFleischer-3316 answered PeterFleischer-3316 commented

Hi Stashy,
try following demo (MVVM with Interactivity).

XAML Main Window:

 <Window x:Class="Window097"
         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:WpfApp1.WpfApp097"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         mc:Ignorable="d"
         Title="211103_StashyCode-7539" Height="450" Width="800">
   <Window.DataContext>
     <local:ViewModel/>
   </Window.DataContext>
   <StackPanel>
     <DataGrid Name="Employees" Height="200"
               AutoGenerateColumns="True"
               CanUserAddRows="False"
               EnableColumnVirtualization="True" 
               EnableRowVirtualization="True"
               ItemsSource="{Binding EmployeesDataTable}"
               SelectionUnit="CellOrRowHeader"
               VirtualizingPanel.VirtualizationMode="Recycling">
       <i:Interaction.Behaviors>
         <local:DataGridBehavior/>
       </i:Interaction.Behaviors>
     </DataGrid>
     <Label Content="{Binding Info}"/>
   </StackPanel>
 </Window>

and classes:

 Imports System.Collections.ObjectModel
 Imports System.ComponentModel
 Imports System.Runtime.CompilerServices
 Imports System.Windows.Interactivity
    
 Namespace WpfApp097
   Public Class ViewModel
     Implements INotifyPropertyChanged
    
     Public Sub New()
       ' Load demo data '
       For i = 1 To 10
         col.Add(New Data With {.ID = i, .Name = $"Row {i}"})
       Next
       cvs.Source = col
     End Sub
    
     Private col As New ObservableCollection(Of Data)
     Private cvs As New CollectionViewSource
    
     Public ReadOnly Property EmployeesDataTable As ICollectionView
       Get
         Return cvs.View
       End Get
     End Property
    
     Private _info As String
     Public Property Info As String
       Get
         Return Me._info
       End Get
       Set(value As String)
         Me._info = value
         OnPropChanged()
       End Set
     End Property
    
     Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
     Private Sub OnPropChanged(<CallerMemberName> Optional propName As String = "")
       RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propName))
     End Sub
   End Class
    
   Public Class Data
     Public Property ID As Integer
     Public Property Name As String
   End Class
    
   Public Class DataGridBehavior
     Inherits Behavior(Of DataGrid)
     Protected Overrides Sub OnAttached()
       AddHandler AssociatedObject.PreviewKeyDown, AddressOf OnPreviewKeyDown
       AddHandler AssociatedObject.PreviewKeyUp, AddressOf OnPreviewKeyUp
     End Sub
    
     Private Sub OnPreviewKeyDown(sender As Object, e As KeyEventArgs)
       If e.Key = Key.F3 Then
         CType(AssociatedObject.DataContext, ViewModel).Info = "Pressed F3"
       ElseIf e.Key = Key.LeftCtrl Then
         LeftCtrl = True
       ElseIf e.Key = Key.F Then
         CType(AssociatedObject.DataContext, ViewModel).Info = "Pressed ctrl left + F"
       End If
     End Sub
    
     Private Sub OnPreviewKeyUp(sender As Object, e As KeyEventArgs)
       If e.Key = Key.LeftCtrl Then
         LeftCtrl = False
       End If
     End Sub
    
     Private LeftCtrl As Boolean = False
    
   End Class
    
 End Namespace

Result:

146132-x.gif

The same code in C#:

 <Window x:Class="WpfApp1.Window079"
         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:Wpf1App079"
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
         mc:Ignorable="d"
         Title="211103_StashyCode-7539" Height="450" Width="800">
   <Window.DataContext>
     <local:ViewModel/>
   </Window.DataContext>
   <StackPanel>
     <DataGrid Name="Employees" Height="200"
               AutoGenerateColumns="True"
               CanUserAddRows="False"
               EnableColumnVirtualization="True" 
               EnableRowVirtualization="True"
               ItemsSource="{Binding EmployeesDataTable}"
               SelectionUnit="CellOrRowHeader"
               VirtualizingPanel.VirtualizationMode="Recycling">
       <i:Interaction.Behaviors>
         <local:DataGridBehavior/>
       </i:Interaction.Behaviors>
     </DataGrid>
     <Label Content="{Binding Info}"/>
   </StackPanel>
 </Window>
    
    
 using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.Runtime.CompilerServices;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Input;
 using System.Windows.Interactivity;
    
 namespace Wpf1App079
 {
   public class ViewModel : INotifyPropertyChanged
   {
    
     public ViewModel()
     {
       // Load demo data
       for (int i = 0; i < 10; i++) col.Add(new Data() { ID = i, Name = $"Row {i}" });
       cvs.Source = col;
     }
    
     private CollectionViewSource cvs = new CollectionViewSource();
     private ObservableCollection<Data> col = new ObservableCollection<Data>();
    
     public ICollectionView EmployeesDataTable { get => cvs.View; }
    
     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)).Info = "Pressed F3";
       else if (e.Key == Key.LeftCtrl) LeftCtrl = true;
       else if (e.Key == Key.F) ((ViewModel)(AssociatedObject.DataContext)).Info = "Pressed ctrl left + F";
     }
    
     private void OnPreviewKeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.LeftCtrl) LeftCtrl = false; }
    
     private bool LeftCtrl = false;
    
   }
 }







x.gif (41.3 KiB)
· 6
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Hello, Peter, thank you very much for your answer! What language is the ViewModel written in? I am using C#, sorry for not specifying!

And one more question - does this searching include a TextBox appearing? Just like (for example) on my Mozilla browser, when I click Ctrl+F a small TextBox appears saying “Find in page”.

0 Votes 0 ·

Hi Stashy,
I add C#-code.

0 Votes 0 ·
StashyCode-7539 avatar image StashyCode-7539 PeterFleischer-3316 ·

Hi, thanks! Can you check the updated version?

0 Votes 0 ·
Show more comments