Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVVM setting default values

Tags:

c#

mvvm

wpf

I'm sure this is a pretty common scenario, and I would like to know how MVVM developers tackle this.

I have a ViewModel that is instantiated on demand, and persists until it is explicitly removed by the user. It's corresponding View is loaded onto the UI on demand. The View is able to unload and it's ViewModel may still exists in the application.

In my scenario, I have a ListBox of preset colors in the View(by setting it's ItemsSource to a Xaml-defined ObservableCollection of SolidColorBrush).

I bound the ListBox's SelectedItem property to a property in the ViewModel so that when the View is to be loaded again, the SelectedItem correctly shows the last selected item in the ListBox and also when the user selects a different color, the VM will handle the change.

My question is, how would u set the default value, say the third item in the ObservableCollection of SolidColorBrush to the ViewModel when the View is first loaded?

like image 580
icube Avatar asked Sep 10 '26 16:09

icube


2 Answers

Usually I set the defaults in the Constructor, unless the defaults may take some time to load, in which case I'll set call a method to set it in the getter for the bound property.

The reason for this is to simplify maintenance. If I am looking for where I set the default value so I can view or change it, the first place I check is the constructor. It's easier to find than scrolling through the properties, and is known to contain initialization logic.

MyViewModel()
{
    // Set defaults 
    SelectedColor = Brushes.Red;
}

For properties that may take longer to load, I use a method that is called in the getter for the same reason. Typically all my properties and their getters/setters are hidden in a region, and I find it much easier to find a method called LoadColors() in my class than finding the Colors properties in the huge list of properties I have. Also, it's reusable, so if I need to do something like reset the value, its easy to do so without repeating my code.

ObservableCollection<SolidColorBrush> Colors
{
    get
    {
        if (_colors == null)
            LoadColors();

        return _colors;
    }
    set { ... }
}

void LoadColors()
{
    // Initialization logic here
}

You can also set the default in your XAML by using the FallbackValue of the binding, however this usually only makes sense when there is a possibility of the binding's DataContext not existing when the binding is evaluated.

<!-- You may have to look up the exact syntax for Brushes.Red -->
<ListBox SelectedItem="{Binding SelectedColor, FallbackValue=Red}" />

And last but not least, you can always resort to code-behind the view to execute view-specific logic like your example. For example,

void ComboBox_Loaded(object obj, EventArgs e)
{
    if (MyComboBox.SelectedIndex == -1)
        MyComboBox.SelectedIndex = 2;
}
like image 156
Rachel Avatar answered Sep 13 '26 05:09

Rachel


I believe you error is in your implementation. The reason to have MVVM is to have a "separation of concerns". That makes your view just an implementation, that can get switched or updated out if/when the need arises. Once you start putting stuff in your view that is part of the application logic, you are traveling down a path of a maintenance headache, and then spaghetti code can quickly ensue.

Some people say, "Don't put any code in your view", I agree 99% of the time. I say "Don't put any domain/application/business logic in your view."

Whenever you're trying to put some code into your view ask yourself "If I switched from WPF to another framework would my app still work?" If the answer is no, then modify your ViewModel to incorporate what you were trying to put in your view.

like image 29
Jose Avatar answered Sep 13 '26 06:09

Jose



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!