2010-08-12 157 views
3

我正在學習WPF mvvm,並且一直在掙扎,我覺得它可能很簡單,但一直無法自行解決。根據另一個選擇填充一個組合框

我想要的是能夠選擇填充組合框中的項目,然後根據該選擇填充另一個組合框。我似乎無法獲得響應選擇加載的第二個組合框。

我已經包含了一個2個組合框和一個文本框的例子。當我運行應用程序並在第一個組合框中選擇一個項目時,將根據綁定更新文本塊,但我不知道在哪裏調用代碼來更新第二個組合框。

我試着將調用添加到SelectedString屬性設置器,但似乎永遠不會被調用。我確信我錯過了一些簡單的東西,但我需要有人幫助揭開面紗!

我試過其他帖子上的建議,但到目前爲止我一直沒有成功。

下面是該視圖的XAML:

<Window x:Class="ThrowAwayMVVMApp.Views.MainView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Main Window" Height="400" Width="800"> 

    <DockPanel> 
     <Grid> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="60*" /> 
       <RowDefinition Height="282*" /> 
      </Grid.RowDefinitions> 
      <!-- Add additional content here --> 
      <ComboBox ItemsSource="{Binding MyStrings}" SelectedItem="{Binding Path=SelectedString, Mode=TwoWay}" Height="23" HorizontalAlignment="Left" Margin="18,24,0,0" Name="comboBox1" VerticalAlignment="Top" Width="204" /> 
      <TextBlock Text="{Binding SelectedString}" Height="23" HorizontalAlignment="Left" Margin="276,24,0,0" Name="textBlock1" VerticalAlignment="Top" Width="227" Background="#FFFAE7E7" /> 
      <ComboBox ItemsSource="{Binding ResultStrings}" Height="23" HorizontalAlignment="Left" Margin="543,25,0,0" Name="comboBox2" VerticalAlignment="Top" Width="189" /> 
     </Grid> 
    </DockPanel> 
</Window> 

這裏是視圖模型:

public class MainViewModel : ViewModelBase 
{ 
    public MainViewModel() 
    { 
     this.MyStrings = new ObservableCollection<string> 
      { 
       "One", 
       "Two", 
       "Three", 
       "Four", 
       "Five" 
      }; 
    } 

    public ObservableCollection<string> MyStrings { get; set; } 
    public ObservableCollection<string> ResultStrings { get; set; } 

    public string SelectedString 
    { 
     get { return (string)GetValue(SelectedStringProperty); } 
     set 
     { 
      SetValue(SelectedStringProperty, value); 
      this.ResultStrings = getResultStrings(value); 
     } 
    } 

    // Using a DependencyProperty as the backing store for SelectedString. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty SelectedStringProperty = 
     DependencyProperty.Register("SelectedString", typeof(string), typeof(MainViewModel), new UIPropertyMetadata("")); 


    private ObservableCollection<string> getResultStrings(string input) 
    { 
     ObservableCollection<string> result = null; 

     if (input == "Three") 
     { 
      result = new ObservableCollection<string> { "Six", "Seven", "Eight" }; 
     } 
     else 
     { 
      result = new ObservableCollection<string> { "Nine", "Ten", "Eleven" }; 
     } 

     return result; 
    } 
} 
+0

,爲什麼你有一個DP您的視圖模型,通常它的意思內宣佈你是綁定的控件中去至? – Agies 2010-08-13 10:55:44

回答

2

的SelectedString依賴屬性的實現是錯誤的:要註冊PropertyChangedCallback時得到通知的DP直接訪問而不是CLR屬性集(請參閱http://msdn.microsoft.com/en-us/library/system.windows.propertychangedcallback.aspx);這樣,即使直接使用DP,您也可以更改相關收集。

當綁定依賴項屬性(如SelectedString)時,WPF綁定不使用CLR屬性設置器,因此您永遠不會調用getResultStrings。順便說一下,我會考慮在視圖模型上使用POCO方法,實現INotifyPropertyChanged:DP是一種很痛苦的寫法,並且給虛擬機添加了很多噪聲(除了對System.Windows的惡意依賴)之外。

看一看這個博客帖子的廣泛的比較:http://kentb.blogspot.com/2009/03/view-models-pocos-versus.html

0

嘗試

private string selectedString; 
public string SelectedString 
{ 
    get { return selectedString; } 
    set 
    { 
     if (selectedString == value) return; 
     selectedString = value; 
     // Required for the UI to know the change was successful 
     RaisePropertyChanged("SelectedString"); 
     LoadStringResults(value); 
    } 
} 

private ObservableCollection<string> resultStrings; 
public ObservableCollection<string> ResultStrings 
{ 
    get { return resultStrings; } 
    set 
    { 
     if (resultStrings== value) return; 
     resultStrings= value; 
     // Required for databinding to know that ResultStrings changed 
     // Previously you changed this property without updating the UI 
     RaisePropertyChanged("ResultStrings"); 
    } 
} 

private void LoadStringResults(string input) 
{ 
    ObservableCollection<string> result = null; 

    if (input == "Three") 
    { 
     result = new ObservableCollection<string> { "Six", "Seven", "Eight" }; 
    } 
    else 
    { 
     result = new ObservableCollection<string> { "Nine", "Ten", "Eleven" }; 
    } 

    ResultStrings = result; 
} 
相關問題