Modifying UI from commands - using command binding

2019-07-28 23:18发布

问题:

In my WPF application I have a TextBox and a Button. The button has a command binding to a command that will do something with the text.

<TextBox x:Name="_textBox"></TextBox>
<Button Command="{Binding SomeCommand}" 
        CommandParameter="{Binding ElementName=_text, Path=Text}"
        Content="Trigger SomeCommand" />

Now, I want the action of clicking the button to also clear the TextBox. What's the best way of doing this? I see two options:

I could add a Click event too on the Button - making this clear the text. This doesn't sound like a good idea to me as I'd be splitting the action in two places, relying on the order they are executed to be correct.

The option I've used for now is to pass the whole TextBox instead of the TextBox.Text property. Doing so the command can first fetch the text, use it, and then clear the TextBox. My binding is the same, but without the "Path":

<TextBox x:Name="_textBox"></TextBox>
<Button Command="{Binding SomeCommand}" 
        CommandParameter="{Binding ElementName=_text}"
        Content="Trigger SomeCommand" />

And the essential parts of my command:

public class SomeCommand : ICommand
{
    ....
    public void Execute(object parameter)
        var textBox = parameter as TextBox;
        if (inputTextBox == null) return; 
        DoSomething(textBox.Text); 
        textBox.Clear();
    }
}

My problem with this is that the command now relies on a UI component, and that the UI depends on the command to actually do some modifications to it. I'm not all comfortable with this. Is there a better way?

回答1:

Please consider binding Textbox text to a property available from Command's implementaion body. Making this bound you can easily clear it from your ViewModel.

Example (XAML):

<TextBox x:Name="_textBox" Text={Binding Path=XYZ}></TextBox>
<Button Command="{Binding SomeCommand}"
        Content="Trigger SomeCommand" />

Example (C#):

    public class SomeCommand : ICommand
    {
        ....

         public void Execute(object parameter)
         {
            //...actions...
            MyViewModelinstance.XYZ = String.Empty;
        }
    }

Please give me a shout if it works.

EDIT: you're using MVVM design pattern, so it should be obvious, but I will remind it just in case: after changing XYZ you have to notify the UI, that this property was changed. You can do it for example by implementing INotifyPropertyChanged Interface by your VM.