我创建了一个自定义控件" CustomAutoCompleteBox" (继承AutoCompleteBox)有一个依赖属性" CurrentItem"。
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绑定到内部属性&#34; InternalItems&#34;和SelectedItem绑定到内部属性&#34; InternalCurrentItem&#34;。
为了使用它,我声明这个CustomAutoCompleteBox如下:
<infrastructure_usercontrols:CustomAutoCompleteBox Width="200" CurrentItem="{Binding DataContext.VmCurrentItem, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}, Mode=TwoWay}" />
我绑定了依赖属性&#34; CurrentItem&#34;到ViewModel的属性&#34; VmCurrentItem&#34;。
除了一件事以外,一切正常。
当我在控件中键入文本时,InternalCurrentItem属性会正确更改。与我的ViewModel中的CurrentItem属性相同。
具体而言,正确修改了InternalCurrentItem(Set)。此属性设置CurrentItem依赖项属性,此依赖项属性设置VmCurrentItem。
反之则不然。如果我直接更改ViewModel中VmCurrentItem属性的值,则不会更改CurrentItem属性。我不明白为什么。
答案 0 :(得分:1)
第一种情况会导致以下事件链:
SelectedItem
已更改InternalCurrentItem
由框架更新
CurrentItem
setter InternalCurrentItem
由于绑定,VmCurrentItem
由框架更新
相反的方向就是这样:
VmCurrentItem
已更改CurrentItem
由框架更新
......就是这样。当InternalCurrentItem
发生变化时,没有任何约束,也没有任何代码可以更新CurrentItem
。因此,您需要为PropertyChangedCallback
注册一个CurrentItemProperty
,这将更新InternalCurrentItem
:
public static readonly DependencyProperty CurrentItemProperty =
DependencyProperty.Register(
"CurrentItem",
typeof(CityEntity),
typeof(CustomAutoCompleteBox),
new FrameworkPropertyMetadata
{
BindsTwoWayByDefault = true,
PropertyChangedCallback = CurrentItemPropertyChanged
});
private static void CurrentItemPropertyChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (CustomAutoCompleteBox)d;
control.InternalCurrentItem = (CityEntity)e.NewValue;
}
答案 1 :(得分:0)
您需要以与第一个相同的方式声明属性:
public static readonly DependencyProperty InternalCurrentItemProperty =
DependencyProperty.Register("InternalCurrentItem", typeof(CityEntity), typeof(CustomAutoCompleteBox),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public CityEntity InternalCurrentItem
{
get{ return (CityEntity)GetValue(InternalCurrentItemProperty); }
set
{
SetValue(InternalCurrentItemProperty, value);
}
}