Wpf MVVM How to handle TextBox “paste event” in th

2019-05-21 07:07发布

I develop application with using MVVM pattern. I using MVVMLight library to do this. So if I need to handle TextBox TextChange event I write in XAML:

<I:EventTrigger EventName="TextChanged">
    <I:InvokeCommandAction Command="{Binding PropertyGridTextChange}"/>
</I:EventTrigger>

where PropertyGridTextChange is Command in ViewModel. But TextBox has no Paste event!

This solution only works if application don't use MVVM pattern, because you need to have link on TextBox.

<DataTemplate x:Key="StringTemplate">
    <TextBox Text="{Binding Value, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    </TextBox>
</DataTemplate>

Important detail - TextBox placed within DataTemplate. I have no idea how can I handle "paste event". I want PasteCommand to be invoked when I paste text into TextBox. And I need that TextBox.Text or TextBox itself to be passed as parameter into PasteCommandMethod.

private RelayCommand<Object> _pasteCommand;
public RelayCommand<Object> PasteCommand
{
    get
    {
        return _pasteCommand ?? (_pasteCommand =
            new RelayCommand<Object>(PasteCommandMethod));
    }
}

private void PasteCommandMethod(Object obj)
{
} 

2条回答
ら.Afraid
2楼-- · 2019-05-21 07:31

I've been struggling with this kind of problem too in recent days. My first approach would be to have a property in the VM that is bound to the text box (which I am sure you already have). Then bind an ICommand to an event to handle the on paste event:

            xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="RowEditEnding">
                <i:InvokeCommandAction Command="{Binding DocRowEdit}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>

you need to define the namespace in the proper part of the XAML code, and then put the interaction triggers in as part of the textbox definition. Here I am capturing the RowEditEnding event to do some stuff similar to what you are attempting.

The command binding is another piece, let me know if you need more information on how that needs to be set up.

查看更多
手持菜刀,她持情操
3楼-- · 2019-05-21 07:52

I can suggest answer on my question.

Class-helper.

public class TextBoxPasteBehavior 
{
public static readonly DependencyProperty PasteCommandProperty =
    DependencyProperty.RegisterAttached(
        "PasteCommand",
        typeof(ICommand),
        typeof(TextBoxPasteBehavior),
        new FrameworkPropertyMetadata(PasteCommandChanged)
    );

public static ICommand GetPasteCommand(DependencyObject target)
{
    return (ICommand)target.GetValue(PasteCommandProperty);
}

public static void SetPasteCommand(DependencyObject target, ICommand value)
{
    target.SetValue(PasteCommandProperty, value);
}

static void PasteCommandChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
    var textBox = (TextBox)sender;
    var newValue = (ICommand)e.NewValue;

    if (newValue != null)
        textBox.AddHandler(CommandManager.ExecutedEvent, new RoutedEventHandler(CommandExecuted), true);
    else
        textBox.RemoveHandler(CommandManager.ExecutedEvent, new RoutedEventHandler(CommandExecuted));

}

static void CommandExecuted(object sender, RoutedEventArgs e)
{
    if (((ExecutedRoutedEventArgs)e).Command != ApplicationCommands.Paste) return;

    var textBox = (TextBox)sender;
    var command = GetPasteCommand(textBox);

    if (command.CanExecute(null))
        command.Execute(textBox);
}
}

Using in XAML. In TextBox as attribute.

TextBoxPasteBehavior.PasteCommand="{Binding PropertyGridTextPasted}"

PropertyGridTextPasted - Command in the ViewModel.

查看更多
登录 后发表回答