【发布时间】:2011-08-31 01:47:53
【问题描述】:
我正在尝试通过一个简单的示例来掌握 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 的方式是否理想。
我无法实现的实际上是对组合框2 的基础集合中的更改做出反应,例如,当列表为空时(即在组合框1 中选择“ccc”时)停用控件。
当然,我可以在 ObservableCollection 的 CollectionChanged 事件上使用事件处理程序,这在本示例中会起作用,但在更复杂的场景中,ComboBox 的 DataContext 可能会更改为完全不同的对象(并且可能back),这将意味着双重依赖——我不仅要切换 DataContext,还要来回切换事件处理程序。这对我来说似乎不对,但我可能只是在这个完全错误的轨道上。
基本上,我正在寻找的是在控件而不是底层列表上触发的事件;不是 ObservableCollection 宣布“我的内容已更改”,而是 ComboBox 告诉我“我的项目发生了一些事情”。
我需要做什么,或者我必须在哪里纠正我对整个概念的看法?
【问题讨论】:
标签: wpf data-binding binding