0

我有一个带有组合框的窗口。这个组合框有 5 个 ComboboxItems。

在示例中,我希望无法选择项目 3、4 和 5。

我尝试了两种不同的方式:MVVM方式代码隐藏方式

MVVM方式:

xml:

<ComboBox SelectedIndex="{Binding Path=SaveIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding Path=SaveSelectedItemCheck}" Name="SaveCombobox">

视图模型:

public object SaveSelectedItemCheck
{
    get { return _control.SaveCombobox.Items[CurrentSaveIndex]; }
    set
    {
        if (value != _control.SaveCombobox.Items[0] && value != _control.SaveCombobox.Items[1])
        {
            OnPropertyChanged("SaveSelectedItemCheck");
        }
    }
}

代码隐藏方式:

xml:

<ComboBox SelectedIndex="{Binding Path=SaveIndex, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="Save_SelectionChanged">

代码隐藏:

private void Save_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ComboBox combobox = sender as ComboBox;
    if(combobox == null)
    {
        return;
    }

    if (combobox.SelectedItem != combobox.Items[0] && combobox.SelectedItem != combobox.Items[1])
    {
        combobox.SelectedItem = combobox.Items[1];
        e.Handled = true;
    }
}

但它只适用于代码隐藏方式,这是肮脏的。

为什么不能以 MVVM 方式工作?

4

3 回答 3

1

您的 ViewModel 方法不会设置属性的值 - 无论该值是否有效。它只是根据值是否有效触发一个事件。

事实上,仔细检查后,您似乎对 MVVM 模式有所误解,因为您的 ViewModel 代码似乎直接引用了它所支持的控件。根据“正常”属性,您应该为您的属性提供一个支持字段。

更重要的是,无论该值是否有效,您都应该抛出该事件,因为如果该值已被视图模型覆盖,那么将通知 UI 组合框值需要重新设置为有效值。PropertyChangedPropertyChanged

于 2012-08-10T13:49:18.640 回答
1

正如其他人所说,您实际上并没有在属性设置器中设置任何值。

但更重要的是 IMO,我认为您误解了 MVVM 的关键概念。您的 ViewModel 代码存在很多问题:

public object SaveSelectedItemCheck
{
    get { return _control.SaveCombobox.Items[CurrentSaveIndex]; }
    set
    {
        if (value != _control.SaveCombobox.Items[0] && value != _control.SaveCombobox.Items[1])
        {
            OnPropertyChanged("SaveSelectedItemCheck");
        }
    }
}

您指的_control.SaveCombobox.Items是 UI 概念/对象。这不是 ViewModel 的目标。而且您正在返回一个对象,您应该强烈键入您的模型!

您应该拥有以下内容:

  • 一个模型(强类型 POCO 类)
  • 不以任何方式处理视图控件的ViewModel (您甚至可以将视图和 ViewModel 分离到不同的程序集中,以确保您遵循此规则)
  • 视图,绑定到ItemsSource控件,例如Combobox

模型:

public class SomeObject : INotifyPropertyChanged
{
    private string someProperty;
    public string SomeProperty
    {
        get { return this.someProperty; }
        set
        {
            if (this.someProperty != value)
            {
                this.someProperty = value;
                OnPropertyChanged("SomeProperty");
            }
        }
    }
    ...
}

视图模型:

public class ViewModel : SomeViewModelBase
{
    private ObservableCollection<SomeObject> items;
    private SomeObject selectedItem;

    public ObservableCollection<SomeObject> Items
    {
        get
        {
            return items;
        }
        set
        {
            if (this.items != value)
            {
                this.items = value;
                OnPropertyChanged("Items");
            }
        }
    }

    public ObservableCollection<SomeObject> SelectedItem
    {
        get
        {
            return selectedItem;
        }
        set
        {
            if (this.selectedItem != value)
            {
                this.selectedItem = value;
                OnPropertyChanged("SelectedItem");
            }
        }
    }

    ...

    // Anywhere in your view model:
    this.Items = new ObservableCollection<SomeObject>(...);
    this.SelectedItem = this.Items[2];
    // Etc.
}

看法:

<ComboBox 
    ItemsSource={Binding Items}
    SelectedItem="{Binding SelectedItem, Mode=TwoWay}">

查看代码隐藏:

没有你的例子

于 2012-08-10T14:27:43.577 回答
0

您不会以 MVVM 方式在 setter 中存储任何值。

于 2012-08-10T13:43:38.793 回答