C# 未从ViewModel设置依赖项属性
我创建了一个自定义控件“CustomAutoCompleteBox”(继承AutoCompleteBox),其中包含一个依赖属性“CurrentItem” 此自定义控件还有一个属性“InternalCurrentItem” DataContext在构造函数中自己定义:C# 未从ViewModel设置依赖项属性,c#,wpf,xaml,binding,custom-controls,C#,Wpf,Xaml,Binding,Custom Controls,我创建了一个自定义控件“CustomAutoCompleteBox”(继承AutoCompleteBox),其中包含一个依赖属性“CurrentItem” 此自定义控件还有一个属性“InternalCurrentItem” DataContext在构造函数中自己定义: public VilleAutoCompleteBox() { DataContext = this; ... } 样式集ItemsSource和SelectedItem如下所示
public VilleAutoCompleteBox()
{
DataContext = this;
...
}
样式集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
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); }
}
public CityEntity InternalCurrentItem
{
get { return _internalCurrentCity; }
set
{
if (_internalCurrentCity == value) return;
_internalCurrentCity = value;
OnPropertyChanged();
CurrentItem = value;
}
}
事实并非如此。如果我直接更改ViewModel中VmCurrentItem属性的值,则CurrentItem属性不会更改。我不明白为什么。您需要以与第一个相同的方式声明属性:
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);
}
}
第一种情况导致以下事件链:
已更改SelectedItem
由于绑定而由框架更新InternalCurrentItem
- 您可以在
设置程序中手动更新InternalCurrentItem
CurrentItem
由于绑定而由框架更新VmCurrentItem
已更改VmCurrentItem
由于绑定而由框架更新CurrentItem
CurrentItem
更改时,没有绑定,也没有更新InternalCurrentItem
的代码。因此,您需要做的是为您的CurrentItemProperty
注册一个PropertyChangedCallback
,它将更新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;
}
附加精度小:当我在ViewModel中直接更改VmCurrentItem属性的值时,CurrentItem属性不会更改。但事实恰恰相反。修改CurrentItem时,VmCurrentItem已更改。问题不是来自InternalCurrentItem。谢谢您非常清晰准确的回答。但我带来了一点修正。与此相反,CurrentItem不会更新:(这是我不理解的一点。如果正确修改了CurrentItem,我将不得不手动更改InternalCurrentItem,如您的示例所示。是的,我刚刚注意到。您的视图模型是否会引发
属性更改
?您是否在输出窗口中收到任何与绑定相关的消息?此外,如果您使用某种view-model注入确保您正在修改控件绑定到的同一视图模型实例。是的,ViewModel提升属性已更改:public CityEntity VmCurrentItem{get{return}VmCurrentItem;}set{if(_VmCurrentItem==value)return;_vmCurrentItem=value;OnPropertyChanged(()=>vmCurrentItem);}输出窗口中没有任何内容。我通过添加PropertyChangedCallBack解决了此问题。请注意,通常不应将控件的DataContext设置为自身,因为这会阻止控件继承其父控件或窗口的DataContext。当您查看当前的复杂性时,可以很容易找到此规则的证据ntItem绑定。最好简单地使用RelativeSource编写控件的“内部”绑定。例如,请参阅以下答案:我已按照您的建议更新了代码。这更简洁,但无法解决问题。