2012-08-10 33 views
0

我有一個窗口與組合框。這個comboboxhas有5個ComboboxItems。修改SelectedItem不適用於MVVM

在這個例子中我想,這是無法選擇的項目3,4和5

我已經試過兩種不同的方式:MVVM方式代碼隱藏方式

MVVM方式:

XAML:

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

代碼隱藏方式:

XAML:

<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方式?

+0

爲什麼你綁定selectedindex和selecteditem。只需使用SelectedItem。另一種方法是將你的itemssource綁定到一個CollectionView。 collectionView將包含所選屬性,因此您不必綁定到selecteditem – 2012-08-10 13:43:30

回答

1

正如其他人所說,你實際上並沒有在屬性設置器中設置任何值。

但更重要的IMO,我認爲你誤會了MVVM的關鍵概念。有很多的問題與您的視圖模型代碼:

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類)
  • 的ViewModels 不與視圖控件以任何方式處理(你甚至可以獨立意見和ViewModels到不同的程序集,以確保您遵循此規則)
  • 視圖,與約束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}"> 

查看後臺代碼:

沒有您例如

0

您不以MVVM方式在設置器中存儲任何值。

+0

+1,發佈的代碼也不會更改所選索引。 – 2012-08-10 13:48:50

+0

@狂野downvoter,謹慎解釋? – 2012-08-10 15:36:00

1

您的ViewModel方法不會設置該屬性的值 - 無論該值是否有效。它只是基於值是否有效而觸發事件。

事實上,仔細觀察,你似乎有點誤解了MVVM模式,因爲看起來你的ViewModel代碼可能直接指向它所支持的控件。根據「正常」屬性,您應該有一個屬性的後臺字段。

更重要的是,你應該拋出PropertyChanged事件的值是否有效或無效的,因爲如果該值已經由視圖模型重寫,然後PropertyChanged將通知組合框的值需要重新設置到UI一個有效的值。