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!"); }
    }
}
War es hilfreich?

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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top