通过自定义依赖属性绑定到 ComboBox.SelectedItem
今天我们来探讨如何在 UserControl 中通过自定义依赖属性绑定到 ComboBox.SelectedItem 属性。
今天我们来探讨如何在 ComboBox.SelectedItem
属性通过自定义依赖属性在 UserControl
中进行数据绑定。
文章第 42 篇
但在开始之前,我想告诉大家,这是 Developers 42 上的第 42 篇文章。出于显而易见的原因,这篇博客文章对我来说意义非凡。去年刚开始的时候,我没有任何访客,但现在平均每月有大约 1700 次访问。其中很大一部分访问来自 Google,但特别感谢 Dave Campbell 在 SilverlightCream.com 上发表了我的许多文章。通过他为我们带来 Silverlight 最新和最棒的内容,他的网站是仅次于 Google 的第二大推荐来源。我不会再详细说明了。统计数据、高峰和低谷都将在博客庆祝成立一周年之际于十月份发布。
在 UserControl
中通过自定义依赖属性绑定到 ComboBox.SelectedItem
,我在构建一个基于以下需求的 UserControl 时遇到了这个问题:我们需要一个组合框,在需要时在其旁边包含一个编辑按钮,并在需要时提供一个标签。实现此目的最简单的方法(至少在我看来)是构建两个 UserControl
。第一个将 ComboBox
与 Button
组合在一起,第二个将结果与 TextBlock
组合在一起。今天我们想专注于第一个,我将其命名为 ExtendedComboBox
。我编写了以下 XAML 作为起点
<UserControl
xmlns:input="clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls.Input"
xmlns:inputToolkit="clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls.Input.Toolkit"
x:Class="ExtendedComboBox.ExtendedComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
x:Name="extendedComboBoxControl"
>
<StackPanel x:Name="stackPanel" Orientation="Horizontal" HorizontalAlignment="Stretch">
<ComboBox x:Name="comboBox"
HorizontalAlignment="Stretch"
SelectionChanged="comboBox_SelectionChanged"
>
</ComboBox>
<Button x:Name="editButton" Content="..." Padding="5,0,5,0"
LayoutUpdated="editButton_LayoutUpdated"
Click="editButton_Click"/>
</StackPanel>
</UserControl>
很简单。我现在只需要添加一些依赖属性来控制一些功能,对吧? 错了! 我不会向你透露有关大小调整和事件的具体细节,因为这不是本文的重点。
为了进行数据绑定,我认为我需要绑定到 ComboBox
的 ItemsSource
和 SelectedItem
属性。这是我最初想到的代码
publicIEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set
{
SetValue(ItemsSourceProperty, value);
comboBox.ItemsSource = value;
}
}
// Using a DependencyProperty as the backing store for ItemsSource.
// This enables animation, styling, binding, etc...
publicstaticreadonlyDependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
typeof(ExtendedComboBox), newPropertyMetadata(null));
publicobject SelectedItem
{
get { return (object)GetValue(SelectedItemProperty); }
set
{
SetValue(SelectedItemProperty, value);
comboBox.SelectedItem = SelectedItem;
}
}
// Using a DependencyProperty as the backing store for SelectedItem.
// This enables animation, styling, binding, etc...
publicstaticreadonlyDependencyProperty SelectedItemProperty =
DependencyProperty.Register("SelectedItem", typeof(object), typeof(ExtendedComboBox),
newPropertyMetadata(null));
如你所见,这些是标准的依赖属性,我只是添加了一行代码,通过它们将值分配给 ComboBox
。对于 ItemsSource
属性,这工作得很好,但是对于 SelectedItem
属性,它不起作用。
在为此苦苦挣扎、构建一个完整的测试平台以及阅读大量博客文章之后,我终于找到了以下解决方案。我删除了在属性 setter 方法中传递值的操作,并在 ExtendedCombobox
的构造函数中添加了手动绑定。这是我的新构造函数
public ExtendedComboBox()
{
InitializeComponent();
Binding selectedItemBinding = newBinding("SelectedItem");
selectedItemBinding.Source = this;
selectedItemBinding.Mode = BindingMode.TwoWay;
comboBox.SetBinding(ComboBox.SelectedItemProperty, selectedItemBinding);
}
这样,ExtendedComboBox
就成为了 ComboBox.SelectedItem
属性绑定的源。在添加此代码(并且显然也实现了涉及的业务对象上的 Equals
和 GetHashCode
方法)之后,它现在工作得很好,而无需在使用的模块中编写任何额外的代码。
如果您有任何问题、意见或只是想打个招呼,请留下评论。