4

I have a viewModel with these three properties:

string searchString;
ObservableCollection<Company> ListedItems;
ICommand SearchCommand;

It represents a searchable list of companies in my database. SearchCommand searches the database based on the value of searchString, and then populates ListedItems with the results.

SearchString is bound to a textbox, while SearchCommand is bound to a button. I want to make it so that as the user types into the text box, SearchCommand is automatically executed without the user having to click the button.

At the moment, I do this via my viewModel:

public ListViewModel() {
    this.PropertyChanged += delegate(object o, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "SearchString")
            SearchCommand.Execute(null);
    };
}

Is this correct? Would it be better to have this functionality in the view? If so, how is that achieved?

Oliver
  • 11,297
  • 18
  • 71
  • 121

3 Answers3

3

A more appropriate solution in my opinion would be to call the command from the setter of your SearchString property on the ViewModel.

Dror
  • 2,548
  • 4
  • 33
  • 51
  • hooking into PropertyChanged is more convinient as it only happens when the property is changed (rather than set to the same value) also in the real viewModel there are several different string properties that are searched on. – Oliver May 02 '12 at 12:04
  • @Oliver in the setter, you can do `if (myProperty == value){ return; }`. this way, you avoid "set to the same value" (and in my opinion, you shouldn't fire any propertyChanged events when the value isn't changed anyway) – default May 02 '12 at 14:14
2

Personally I would consider using the Expression Blend SDK InvokeCommandAction.

I knocked an example that worked. Here is the view:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="WpfApplication1.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <StackPanel>
            <TextBox Text="Hello World">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="TextChanged">
                        <i:InvokeCommandAction Command="{Binding DoItCommand}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBox>
            <Button x:Name="CommandButton" Command="{Binding DoItCommand}" Content="Click me" />
        </StackPanel>
    </Grid>
</Window>

And a very simple ViewModel (that uses PRISM's DelegateCommand):

 public class SomeViewModel
    {
        public SomeViewModel()
        {
            DoItCommand = new DelegateCommand(() => Debug.WriteLine("It Worked"));
        }

        public ICommand DoItCommand { get; private set; }
    }

The code behind simple wires up the ViewModel:

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new SomeViewModel();
        }
    }

You don't need to have Expression Blend to do this either- the SDK is free to download and use.

If you don't fancy using the Expression Blend SDK, MVVM Light offers EventToCommand, which is similar.

Of course doing this only really makes sense if there is still a reason to have the button in place (or you wish to utilise the command's can execute logic), otherwise you can fire off some logic in the setter off the property.

RichardOD
  • 28,883
  • 9
  • 61
  • 81
1

Better bind command to TextBox. Maybe this will be helpfull.

Community
  • 1
  • 1
Zabavsky
  • 13,340
  • 8
  • 54
  • 79