How to do caliburn.micro binding of view model to combobox selected value?
Asked Answered
P

1

14

I'm relatively low on the curve for both WPF and Caliburn.Micro.

My goal here is to move the binding of the combobox selected item from the ShellView's code behind to the View Model, the same as it already is for the combobox's item collection.

XAML:

<Window x:Class="EomDatabaseUtility.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Eom Tool Database Utility" Height="350" Width="525">
    <Grid>
        <DataGrid AutoGenerateColumns="False" Height="258" HorizontalAlignment="Left" Margin="12,41,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="479" />
        <Button Content="Execute" Height="23" HorizontalAlignment="Left" Margin="416,12,0,0" VerticalAlignment="Top" Width="75" x:Name="Execute" />
        <ComboBox Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" VerticalAlignment="Top" Width="120" x:Name="CatalogName" SelectedValuePath="{Binding Path=SelectedCatalogName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</Window>

Code Behind (where the goal is to not have to add any code, if I uderstand correctly):

namespace EomDatabaseUtility.Views
{
    using System.Windows;

    public partial class ShellView : Window
    {
        public ShellView()
        {
            InitializeComponent();
        }

        // --> This should go in the view model, Right?
        private string selectedCatalogName;
        public string SelectedCatalogName
        {
            get { return selectedCatalogName; }
            set { selectedCatalogName = value; }
        }
    }
}

View Model (currently supplying the collection of items to the combobox as well as a button event handler):

namespace EomDatabaseUtility.ViewModels
{
    using Caliburn.Micro;
    using System.Collections.Generic;

    public class ShellViewModel : PropertyChangedBase
    {
        public List<string> CatalogName
        {
            get
            {
                return new List<string> { "foo", "bar" };
            }
        }

        public void Execute()
        {
            System.Windows.MessageBox.Show("hello");
        }
    }
}
Predicable answered 7/3, 2012 at 20:6 Comment(0)
E
37

You can bind the SelectedItem of the ComboBox to a property on your view model:

<ComboBox x:Name="CatalogName" ... SelectedItem="{Binding SelectedCatalog}" />

public class ShellViewModel : PropertyChangedBase
{
    private string selectedCatalog;

    public List<string> CatalogName
    {
        get
        {
            return new List<string> { "foo", "bar" };
        }
    }

    public string SelectedCatalog
    {
       get
       {
          return this.selectedCatalog;
       }

       set
       {
          this.selectedCatalog = value;
          this.NotifyOfPropertyChange(() => this.SelectedCatalog);
       }
    }

In fact, because your ComboBox has a name of CatalogName, the Caliburn.Micro conventions will look for a property called SelectedCatalogName (or ActiveCatalogName) and automatically bind the ComboBox's SelectedItem to that, so therefore you can use:

<ComboBox x:Name="CatalogName" ... />

public string SelectedCatalogName
{
  ...
}

A few things to note:

  • We call NotifyOfPropertyChange() in the setter for the SelectedCatalog. This notifies the UI that the value has changed whenever we set it from the view model, so that the UI gets updated. This method is part of PropertyChangedBase.
  • You should really use a collection type which supports collection changed notifications in your view models, such as ObservableCollection which comes with WPF, or Caliburn.Micro's BindableCollection (which implements Caliburn.Micro's IObservableCollection). This allows the UI to be notified when objects are added/removed from your collections from the view model.
  • Your shell view model should probably implement a Screen or Conductor type (rather than PropertyChangedBase) if it's going to have a life cycle (activation/deactivation etc), or going to have a currently active item (screen) which can change at run time.
Ebullience answered 7/3, 2012 at 20:24 Comment(2)
thank you! I got it working with the SelectedItem property, but not SelectedCatalogName - however, that's just a bonus anyway...Predicable
Ah, you might try naming the combobox CatalogNames, and then have a CatalogNames property, and SelectedCatalogName. I would expect that to work.Ebullience

© 2022 - 2024 — McMap. All rights reserved.