Programmatisch einstellen der aktuellen Zelle ohne Unterbrechung der Registerkartenfunktionalität
Posted: 21 May 2025, 12:16
Ich versuche, die aktuelle Zelle eines WPF-Datagrids programmatisch festzulegen und den Bearbeitungsmodus wie diesen zu starten: < /p>
Eigenschaft dieses Textfelds ist in meinem ViewModel an einen EigenschaftssuchText gebunden. Ich verwende dann ReactiveUi, um Benutzereingaben wie folgt zu verarbeiten: < /p>
Die Funktion searchandfocus () prüft dann, ob eine übereinstimmende Zeile basierend auf dem im Feld Suchstudio eingegebenen Text gefunden werden kann. Wenn ein Match gefunden wurde, wird FocusRequested aufgerufen. FocusRequested wird dann in der Ansicht von meiner OnfocusRequested -Funktion behandelt. Die Zelle ist ausgewählt und wird bearbeitet. Wenn der Benutzer jedoch Registerkarte während des Bearbeitens dieser Zelle drückt, anstatt sich in derselben Zeile zur nächsten Spalte zu bewegen, springt der Fokus zurück zum Suchtext.
Dies ändert das Verhalten nicht - Drücken Sie Registerkarte springt immer noch zum Suchfeld, anstatt innerhalb des Datagrid zu navigieren. Ich habe auch versucht, das Netz zuerst zu konzentrieren, aber egal was ich versuche, ich kann dieses Verhalten nicht ändern. Hier ist ein minimal reproduzierbares Beispiel: < /p>
Mainwindow.xaml:
< /code>
Mainwindow.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1;
public partial class MainWindow : Window
{
private readonly MainWindowViewModel mainWindowViewModel;
public MainWindow()
{
InitializeComponent();
mainWindowViewModel = new MainWindowViewModel();
mainWindowViewModel.FocusRequested += OnFocusRequested;
this.DataContext = mainWindowViewModel;
}
private void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.Column == PunktzahlColumn && e.EditAction == DataGridEditAction.Commit && SearchTextBox.Text.Length > 0)
{
SearchTextBox.Focus();
mainWindowViewModel.SearchText = string.Empty;
}
}
private void OnFocusRequested(MyViewModel myViewModel)
{
MyDataGrid.UnselectAllCells();
MyDataGrid.CurrentCell = new DataGridCellInfo(myViewModel, PunktzahlColumn);
MyDataGrid.BeginEdit();
}
}
< /code>
MainwindowViewModel.cs
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Collections.ObjectModel;
using System.Reactive.Linq;
using System.Windows;
namespace WpfApp1;
public class MainWindowViewModel : ReactiveObject
{
private ObservableCollection myViewModels;
public IEnumerable MyViewModels => myViewModels;
public event Action? FocusRequested;
[Reactive]
public string? SearchText { get; set; }
public MainWindowViewModel()
{
myViewModels = new ObservableCollection();
for (int i = 0; i < 10; i++)
{
myViewModels.Add(new MyViewModel($"Name {i}", i * 10, $"Kommentar {i}"));
}
this.WhenAnyValue(x => x.SearchText)
.Throttle(TimeSpan.FromMilliseconds(300))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => searchAndFocus());
}
private void searchAndFocus()
{
if (string.IsNullOrWhiteSpace(SearchText))
{
return;
}
var matches = MyViewModels
.Where(b => b.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase))
.ToList();
if (matches.Count == 1)
{
// Set focus with delay
Application.Current.Dispatcher.InvokeAsync(() =>
{
FocusRequested?.Invoke(matches[0]);
});
}
}
}
< /code>
MyViewModel.cs:
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
namespace WpfApp1;
public class MyViewModel : ReactiveObject
{
[Reactive]
public string Name { get; set; }
[Reactive]
public int? Punktzahl { get; set; }
[Reactive]
public string? Kommentar { get; set; }
public MyViewModel(string name, int? punktzahl, string? kommentar)
{
Name = name;
Punktzahl = punktzahl;
Kommentar = kommentar;
}
}
< /code>
Abhängigkeiten: < /p>
ReactiveUi Version 20.2.45 < /li>
ReactiveUi.FODY Version 19.5.41 < /li>
öten>
Code: Select all
MyDataGrid.CurrentCell = new DataGridCellInfo(myViewModel, PunktzahlColumn);
MyDataGrid.BeginEdit();
< /code>
Dieser Code wird ausgeführt, nachdem der Benutzer etwas in ein Suchtextfeld über dem Raster eingeleitet hat. Die text
Code: Select all
this.WhenAnyValue(x => x.SearchText)
.Throttle(TimeSpan.FromMilliseconds(300))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => searchAndFocus());
Code: Select all
Dispatcher.InvokeAsync(() =>
{
var cellContent = PunktzahlColumn.GetCellContent(MyDataGrid.CurrentItem);
if (cellContent != null)
{
var textBox = FindVisualChild(cellContent);
textBox?.Focus();
}
});
Mainwindow.xaml:
< /code>
Mainwindow.xaml.cs:
using System.Windows;
using System.Windows.Controls;
namespace WpfApp1;
public partial class MainWindow : Window
{
private readonly MainWindowViewModel mainWindowViewModel;
public MainWindow()
{
InitializeComponent();
mainWindowViewModel = new MainWindowViewModel();
mainWindowViewModel.FocusRequested += OnFocusRequested;
this.DataContext = mainWindowViewModel;
}
private void MyDataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
if (e.Column == PunktzahlColumn && e.EditAction == DataGridEditAction.Commit && SearchTextBox.Text.Length > 0)
{
SearchTextBox.Focus();
mainWindowViewModel.SearchText = string.Empty;
}
}
private void OnFocusRequested(MyViewModel myViewModel)
{
MyDataGrid.UnselectAllCells();
MyDataGrid.CurrentCell = new DataGridCellInfo(myViewModel, PunktzahlColumn);
MyDataGrid.BeginEdit();
}
}
< /code>
MainwindowViewModel.cs
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Collections.ObjectModel;
using System.Reactive.Linq;
using System.Windows;
namespace WpfApp1;
public class MainWindowViewModel : ReactiveObject
{
private ObservableCollection myViewModels;
public IEnumerable MyViewModels => myViewModels;
public event Action? FocusRequested;
[Reactive]
public string? SearchText { get; set; }
public MainWindowViewModel()
{
myViewModels = new ObservableCollection();
for (int i = 0; i < 10; i++)
{
myViewModels.Add(new MyViewModel($"Name {i}", i * 10, $"Kommentar {i}"));
}
this.WhenAnyValue(x => x.SearchText)
.Throttle(TimeSpan.FromMilliseconds(300))
.ObserveOn(RxApp.MainThreadScheduler)
.Subscribe(_ => searchAndFocus());
}
private void searchAndFocus()
{
if (string.IsNullOrWhiteSpace(SearchText))
{
return;
}
var matches = MyViewModels
.Where(b => b.Name.Contains(SearchText, StringComparison.OrdinalIgnoreCase))
.ToList();
if (matches.Count == 1)
{
// Set focus with delay
Application.Current.Dispatcher.InvokeAsync(() =>
{
FocusRequested?.Invoke(matches[0]);
});
}
}
}
< /code>
MyViewModel.cs:
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
namespace WpfApp1;
public class MyViewModel : ReactiveObject
{
[Reactive]
public string Name { get; set; }
[Reactive]
public int? Punktzahl { get; set; }
[Reactive]
public string? Kommentar { get; set; }
public MyViewModel(string name, int? punktzahl, string? kommentar)
{
Name = name;
Punktzahl = punktzahl;
Kommentar = kommentar;
}
}
< /code>
Abhängigkeiten: < /p>
ReactiveUi Version 20.2.45 < /li>
ReactiveUi.FODY Version 19.5.41 < /li>
öten>