wojg21
wojg21

Reputation: 93

Confused as to where to place logic code in ViewModel

I'm new to C#/WPF and I would like some clarification on whether I have the proper implementation of my ViewModel.

I have created a simple window with a search text box and list box for the results.

<TextBox Text="{Binding SearchText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ListBox ItemsSource="{Binding Results}" />

Then I have a ViewModel with the following code.

private List<string> lstStr;

    public ViewModel()
    {
        lstStr = new List<string>();
        lstStr.Add("Mike");
        lstStr.Add("Jerry");
        lstStr.Add("James");
        lstStr.Add("Mikaela");
    }

    public List<string> LstStr
    {
        get
        {                
            return lstStr;
        }

        set
        {
            if (lstStr != value)
            {
                lstStr = value;
                OnPropertyChanged("LstStr");
            }
        }
    }

    private string searchText;
    public string SearchText
    {
        get
        {
            return searchText;
        }

        set
        {
            if (searchText != value)
            {
                searchText = value;
                OnPropertyChanged("SearchText");
                UpdateResults();
            }
        }
    }

    private ObservableCollection<string> results = new ObservableCollection<string>();
    public ObservableCollection<string> Results
    {
        get
        {                
            return results;
        }

        set
        {
            if (results != value)
            {
                results = value;
                OnPropertyChanged("Results");
            }
        }
    }

    public void UpdateResults()
    {
        int i = 0;
        results.Clear();
        while (i < LstStr.Count)
        {
            if (LstStr.ElementAt(i).ToString() != null)
            {
                if (searchText != null && searchText != "")
                {
                    if (LstStr.ElementAt(i).Trim().Contains(searchText))
                    {
                        results.Add(LstStr.ElementAt(i));
                        Console.WriteLine(LstStr.ElementAt(i));
                    }
                }

                else
                    results.Clear();
            }

            else
                Console.WriteLine("NULL");

            i++;
        }
    }

I see myself writing logic in the Get or Set section of code in the ViewModel. Let's say I will have more text boxes and lists that will want to implement. Is this the correct way of coding my logic in the properties or am I completely missing the point? Please help me understand this. Thanks in advance.

Upvotes: 4

Views: 191

Answers (2)

Peter Ritchie
Peter Ritchie

Reputation: 35871

ViewModels should have only the responsibility of "converting" data into another form that the view can handle (think INotifyPropertyChanged, ObservableCollection, etc.)

The only time where you'd get away with the ViewModel having any of the logic is when the logic is encapsulated entirely in a collection. e.g. if you can get everything you need out of List<T>, then the ViewModel effectively has all the logic. If you need value beyond that, it should be outside of the ViewModel.

Upvotes: 3

BradleyDotNET
BradleyDotNET

Reputation: 61349

No, this isn't exactly right.

First, logic normally goes in the model, not the view model. That said, you have a filter, which is basically UI logic, so its probably OK here.

Second, the filter will only change when you set the search text, so the logic would go in the setter, not the getter. I also wouldn't inline the whole thing, put it in its own function so you can reuse it later:

public String SearchText
{
    ...
    set
    {
       serachText = value;
       NotifyPropertyChanged();
       UpdateResults();
    }
}

public void UpdateResults()
{
     ...
}

The one thing to keep in mind (and there isn't really a good way around this) is that if that function takes a long time to run, your UI will really slow down while the user is typing. If the execution time is long, try shortening it, then consider doing it on a separate thread.

Upvotes: 3

Related Questions