如何对Caliburn.Micro进行数据绑定,将视图模型绑定到ComboBox的选定值?

14

我在WPF和Caliburn.Micro方面的掌握程度相对较低。

我的目标是将组合框选定项的绑定从ShellView的代码后台移动到视图模型中,与组合框的项目集合已经实现的方式相同。

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>

代码后台(如果我理解正确的话,目标是不需要添加任何代码):

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; }
        }
    }
}

视图模型(目前作为下拉列表框的条目集合提供者以及一个按钮事件处理程序):

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");
        }
    }
}
1个回答

37

您可以将ComboBoxSelectedItem绑定到视图模型上的一个属性:

<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);
       }
    }

实际上,因为你的 ComboBox 的名称为 CatalogName,Caliburn.Micro 约定将会寻找一个名为 SelectedCatalogName(或者 ActiveCatalogName)的属性,并且自动绑定 ComboBoxSelectedItem 到它,所以你可以使用:

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

public string SelectedCatalogName
{
  ...
}

需要注意以下几点:

  • 我们在SelectedCatalog的setter中调用NotifyOfPropertyChange()。这样,每当从视图模型中设置它时,通知UI值已更改,以便更新UI。该方法是PropertyChangedBase的一部分。
  • 在视图模型中使用支持集合更改通知的集合类型,如WPF自带的ObservableCollection或Caliburn.Micro的BindableCollection(它实现了Caliburn.Micro的IObservableCollection)。这使得当从视图模型中添加/删除对象到您的集合时,可以通知UI。
  • 如果您的外壳视图模型将具有生命周期(激活/停用等)或将具有当前可更改的活动项(屏幕),则应该实现ScreenConductor类型(而不是PropertyChangedBase)。

谢谢!我已经用SelectedItem属性解决了问题,但是SelectedCatalogName还没有。不过,这只是额外的奖励而已… - Aaron Anodide
2
啊,你可以尝试将下拉框命名为CatalogNames,然后拥有一个CatalogNames属性和SelectedCatalogName。我认为这样应该可以工作。 - devdigital

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接