WPF Textbox Abfangen Routeduicommands
-
21-09-2019 - |
Frage
Ich versuche, Rückgängig-/Wiederherstellung von Tastaturverknüpfungen in meiner WPF -Anwendung zu erhalten (ich habe meine eigene benutzerdefinierte Funktionalität mit dem implementiert Befehlsmuster). Es scheint jedoch, dass die TextBox
Die Kontrolle fängt mein "Rückgängig" Routeduicommand ab.
Was ist der einfachste Weg, um dies zu deaktivieren, damit ich Strg+z an der Wurzel meines UI -Baumes fangen kann? Ich möchte vermeiden, eine Menge Code/XAML in jeden einzelnen TextBox
in meiner Bewerbung, wenn möglich.
Das Folgende zeigt kurz das Problem:
<Window x:Class="InputBindingSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:InputBindingSample"
Title="Window1" Height="300" Width="300">
<Window.CommandBindings>
<CommandBinding Command="loc:Window1.MyUndo" Executed="MyUndo_Executed" />
</Window.CommandBindings>
<DockPanel LastChildFill="True">
<StackPanel>
<Button Content="Ctrl+Z Works If Focus Is Here" />
<TextBox Text="Ctrl+Z Doesn't Work If Focus Is Here" />
</StackPanel>
</DockPanel>
</Window>
using System.Windows;
using System.Windows.Input;
namespace InputBindingSample
{
public partial class Window1
{
public static readonly RoutedUICommand MyUndo = new RoutedUICommand("MyUndo", "MyUndo", typeof(Window1),
new InputGestureCollection(new[] { new KeyGesture(Key.Z, ModifierKeys.Control) }));
public Window1() { InitializeComponent(); }
private void MyUndo_Executed(object sender, ExecutedRoutedEventArgs e) { MessageBox.Show("MyUndo!"); }
}
}
Lösung
Es gibt keinen einfachen Weg, um alle Bindungen zu unterdrücken, nicht einstellen IsUndoEnabled
zu false
wie es nur fangen und spülen wird Strg + Z Schlüsselbindung. Sie müssen umleiten CanUndo
, CanRedo
, Undo
und Redo
. So mache ich es mit meinem UndoServiceActions
Singleton.
textBox.CommandBindings.Add(new CommandBinding(ApplicationCommands.Undo,
UndoCommand, CanUndoCommand));
textBox.CommandBindings.Add(new CommandBinding(ApplicationCommands.Redo,
RedoCommand, CanRedoCommand));
private void CanRedoCommand(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = UndoServiceActions.obj.UndoService.CanRedo;
e.Handled = true;
}
private void CanUndoCommand(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = UndoServiceActions.obj.UndoService.CanUndo;
e.Handled = true;
}
private void RedoCommand(object sender, ExecutedRoutedEventArgs e)
{
UndoServiceActions.obj.UndoService.Redo();
e.Handled = true;
}
private void UndoCommand(object sender, ExecutedRoutedEventArgs e)
{
UndoServiceActions.obj.UndoService.Undo();
e.Handled = true;
}
Andere Tipps
Wenn Sie Ihr eigenes Rückgänger/Wiederherstellen implementieren und die Textbox daran hindern möchten, fügen Sie die Befehlsvorschau -Ereignisse durch CommandManager.AddPreviewCanExecuteHandler
und CommandManager.AddPreviewExecutedHandler
und setzen Sie das Ereignis. Behandelte Flagge auf True:
MySomething()
{
CommandManager.AddPreviewCanExecuteHandler(
this,
new CanExecuteRoutedEventHandler(OnPreviewCanExecuteHandler));
CommandManager.AddPreviewExecutedHandler(
this,
new ExecutedRoutedEventHandler(OnPreviewExecutedEvent));
}
void OnPreviewCanExecuteHandler(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Command == ApplicationCommands.Undo)
{
e.CanExecute = true;
e.Handled = true;
}
else if (e.Command == ApplicationCommands.Redo)
{
e.CanExecute = true;
e.Handled = true;
}
}
void OnPreviewExecutedEvent(object sender, ExecutedRoutedEventArgs e)
{
if (e.Command == ApplicationCommands.Undo)
{
// DO YOUR UNDO HERE
e.Handled = true;
}
else if (e.Command == ApplicationCommands.Redo)
{
// DO YOUR REDO HERE
e.Handled = true;
}
}
TextBoxBase
(und somit TextBox
und RichTextBox
) haben IsUndoEnabled
Eigentum, Staub bei true
. Wenn Sie es aufstellen false
(Und Sie können dies für alle Textboxen in Ihrem Fenster über einen Stil und einen Setter wie gewohnt ereignen.)
Standardmäßig das Ziel der RoutedUICommand
ist das Element mit Tastaturfokus. Sie können jedoch festlegen CommandTarget
Auf der Steuerung, um den Befehl zu emittieren, um das Stammelement zu ändern, das den Befehl empfängt.
<MenuItem Command="ApplicationCommands.Open"
CommandTarget="{Binding ElementName=UIRoot}"
Header="_Open" />
Das ausgeführte Ereignis blüht sich auf, sodass das ausgestellte Fenster nach dem Ereignis des Textfelds immer getroffen wird. Versuchen Sie, es in die Vorschau zu ändern, und es sollte einen großen Unterschied machen. Möglicherweise müssen Sie auch einen CaneExecute für Ihr Fenster anschließen. dh:
<CommandBinding Command="Undo" PreviewExecuted="MyUndo_Executed" CanExecute="SomeOtherFunction"/>
private void SomeOtherFunction(object sender, ExecutedRoutedEventArgs e) { e.CanExecute=true; }
Natürlich möchten Sie wahrscheinlich eine Logik, um festzustellen, wann CaneExecute auf true eingestellt werden soll. Sie müssen wahrscheinlich auch keinen benutzerdefinierten Befehl verwenden (verwenden Sie einfach das integrierte Rückgänger).
Das TextBox
Kontrolle liefert an IsUndoEnabled
Eigenschaft, auf die Sie einstellen können false
Um das Rückgängigungs -Merkmal zu verhindern. (Wenn IsUndoEnabled
ist true
, das Strg + Z Tastenanschlag löst es aus.)
Auch für eine Kontrolle, die keine spezielle Eigenschaft bietet, können Sie eine neue Bindung für den Befehl hinzufügen, den Sie deaktivieren möchten. Diese Bindung kann dann eine neue liefern CanExecute
Ereignishandler, der immer falsch reagiert. Hier ist ein Beispiel, das diese Technik verwendet, um die Unterstützung für die Schnittfunktion des Textfelds zu entfernen:
CommandBinding commandBinding = new CommandBinding(
ApplicationCommands.Cut, null, SuppressCommand);
txt.CommandBindings.Add(commandBinding);
Und hier ist der Event -Handler, der die festlegt CanExecute
Zustand:
private void SuppressCommand(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = false;
e.Handled = true;
}