【发布时间】:2017-06-01 07:50:53
【问题描述】:
我用一个依赖属性“CurrentItem”创建了一个自定义控件“CustomAutoCompleteBox”(继承自 AutoCompleteBox)。
public static readonly DependencyProperty CurrentItemProperty =
DependencyProperty.Register("CurrentItem", typeof(CityEntity), typeof(CustomAutoCompleteBox),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public CityEntity CurrentItem
{
get { return (CityEntity)GetValue(CurrentItemProperty); }
set { SetValue(CurrentItemProperty, value); }
}
这个自定义控件还有一个属性“InternalCurrentItem”。
public CityEntity InternalCurrentItem
{
get { return _internalCurrentCity; }
set
{
if (_internalCurrentCity == value) return;
_internalCurrentCity = value;
OnPropertyChanged();
CurrentItem = value;
}
}
DataContext 是在构造函数中自己定义的:
public VilleAutoCompleteBox()
{
DataContext = this;
...
}
Style 设置 ItemsSource 和 SelectedItem 如下:
<Style TargetType="{x:Type infrastructure_controls:CustomAutoCompleteBox}" BasedOn="{StaticResource AutoCompleteBoxFormStyle}">
<Setter Property="ItemsSource" Value="{Binding InternalItems, Mode=OneWay}" />
<Setter Property="SelectedItem" Value="{Binding InternalCurrentItem, Mode=TwoWay}" />
...
</Style>
总之,ItemsSource 绑定到内部属性“InternalItems”,SelectedItem 绑定到内部属性“InternalCurrentItem”。
为了使用它,我这样声明这个 CustomAutoCompleteBox :
<infrastructure_usercontrols:CustomAutoCompleteBox Width="200" CurrentItem="{Binding DataContext.VmCurrentItem, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Mode=TwoWay}" />
我已将依赖属性“CurrentItem”绑定到 ViewModel 的属性“VmCurrentItem”。
除了一件事,一切都很好。
当我在控件中键入文本时,InternalCurrentItem 属性会正确更改。我的 ViewModel 中的 CurrentItem 属性也是如此。
具体来说,InternalCurrentItem 已正确修改(设置)。此属性设置 CurrentItem 依赖属性,此依赖属性设置 VmCurrentItem。
反之则不然。如果我直接更改 ViewModel 中 VmCurrentItem 属性的值,则 CurrentItem 属性不会更改。我不明白为什么。
【问题讨论】:
-
请注意,通常不应将控件的 DataContext 设置为自身,因为它会阻止控件继承其父控件或窗口的 DataContext。当您查看 CurrentItem 绑定的复杂性时,您可以轻松找到此规则的证明。最好用RelativeSource 编写控件的“内部”绑定。参见例如这个答案:stackoverflow.com/a/28982771/1136211
-
我已按照您的建议更新了我的代码。这更干净,但不能解决问题。
标签: c# wpf xaml binding custom-controls