我想通過一個簡單的例子來掌握WPF數據綁定的概念,但似乎我沒有完全明白它的全部意義。WPF數據綁定 - 我錯過了什麼?
該示例是級聯下拉列表中的一個;在XAML如下:
<Window x:Class="CascadingDropDown.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="496" Width="949" Loaded="Window_Loaded">
<Grid>
<ComboBox Name="comboBox1" ItemsSource="{Binding}" DisplayMemberPath="Key" SelectionChanged="comboBox1_SelectionChanged" />
<ComboBox Name="comboBox2" ItemsSource="{Binding}" DisplayMemberPath="Name" />
</Grid>
</Window>
這是形式的代碼:
public partial class MainWindow : Window
{
private ObservableCollection<ItemA> m_lstItemAContext = new ObservableCollection<ItemA>();
private ObservableCollection<ItemB> m_lstItemBContext = new ObservableCollection<ItemB>();
private IEnumerable<ItemB> m_lstAllItemB = null;
public MainWindow()
{
InitializeComponent();
this.comboBox1.DataContext = m_lstItemAContext;
this.comboBox2.DataContext = m_lstItemBContext;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var lstItemA = new List<ItemA>() { new ItemA("aaa"), new ItemA("bbb"), new ItemA("ccc") };
var lstItemB = new List<ItemB>() { new ItemB("aaa", "a11"), new ItemB("aaa", "a22"), new ItemB("bbb", "b11"), new ItemB("bbb", "b22") };
initPicklists(lstItemA, lstItemB);
}
private void initPicklists(IEnumerable<ItemA> lstItemA, IEnumerable<ItemB> lstItemB)
{
this.m_lstAllItemB = lstItemB;
this.m_lstItemAContext.Clear();
lstItemA.ToList().ForEach(a => this.m_lstItemAContext.Add(a));
}
#region Control event handlers
private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ComboBox ddlSender = (ComboBox)sender;
ItemA itemaSelected = (ItemA)ddlSender.SelectedItem;
var lstNewItemB = this.m_lstAllItemB.Where(b => b.KeyA == itemaSelected.Key);
this.m_lstItemBContext.Clear();
lstNewItemB.ToList().ForEach(b => this.m_lstItemBContext.Add(b));
}
private void comboBox2_?(object sender, ?EventArgs e)
{
// disable ComboBox if empty
}
#endregion Control event handlers
}
這些都是我的數據類:
class ItemA
{
public string Key { get; set; }
public ItemA(string sKey)
{
this.Key = sKey;
}
}
class ItemB
{
public string KeyA { get; set; }
public string Name { get; set; }
public ItemB(string sKeyA, string sName)
{
this.KeyA = sKeyA;
this.Name = sName;
}
}
因此,一旦某一項在comboBox1選擇,相應的項目應該顯示在comboBox2中。這與當前的代碼一起工作,但我不確定我的方式是重新填充各自的ObservableCollection是否理想。
我沒有能夠實現的是實際上對comboBox2底層集合的變化作出反應,例如當列表爲空時(即在comboBox1中選擇「ccc」時)停用控件。當然,我可以在ObservableCollection的CollectionChanged事件上使用一個事件處理函數,並且在這個例子中可以工作,但是在更復雜的情況下,ComboBox的DataContext可能會改變爲一個完全不同的對象(和可能會回來),這意味着雙重依賴 - 我總是不得不切換DataContext,而且還要來回切換事件處理程序。這對我來說似乎並不合適,但我可能只是在完全錯誤的軌道上。
基本上,我正在尋找的是一個事件觸發控件而不是基礎列表;而不是ObservableCollection宣佈「我的內容已經改變」,但ComboBox告訴我「我的項目發生了一些事情」。
我需要做什麼,或者我必須在哪裏糾正我對整個概念的理解?
謝謝;這正是我所需要的 - 在繼續研究之前,至少要深入研究MVVM的基礎知識。這看起來很理想,強大的數據綁定顯然消除了UI處理中的很多複雜性 – TeaDrivenDev 2011-05-24 22:25:28