我使用MVVM模式,所以我自己的控件包含View和ViewModel ViewModel与View by DataContext属性相关联。这会产生绑定问题。为什么?
假设这种情况:
我创建了新的用户控件 - 例如 - “SuperTextBox”。它有一个属性“SuperValue”。
现在我做了类似的事情:
<Window>
<Window.DataContext>
<vm:WindowViewModel/>
</Window.DataContext>
<local:SuperTextBox SuperValue="{Binding Test}"/>
</Window>
我认为“绑定进程”将SuperTextBox.SuperValue与Window.DataContext.Test连接起来,但是没有,“绑定进程”将SuperTextBox.SuperValue与SuperTextBox.DataContext.Test连接起来对我来说不自然和误导。
像“TextBox”这样的其他控件我可以用上面的方式,因为它们没有DataContext。
如何使用MVVM模式创建保持自然绑定的UserControl(对于父控件的DataContext)?
编辑:
我得到了许多答案,如何绑定父母,但我早先知道。问题是 - 如何通过MVVM patern创建UserControl(具有ViewModel)并保持自然绑定 - 默认为父DataContext。
我想拥有ViewMoldel并且仍然可以这样绑定:
<local:SuperTextBox SuperValue="{Binding Test}"/>
有可能吗?
答案 0 :(得分:2)
所有绑定都适用于任何control always first look for the binding in its DataContext
。如果没有为控件设置DataContext,那么除非它找到DataContext,否则它walks up the Visual Tree
到它的父级。
即使您将textBox上的DataContext
设置为与Window的DatContext不同的值,它也将始终在该特定DataContext上搜索属性Test
,而不是Window's DataContext
上的属性<TextBox>
<TextBox.DataContext>
<vm:ViewModelForTextBox/>
</TextBox.DataContext>
<TextBox.Text>
<Binding Path="Test"/>
</TextBox.Text>
</TextBox>
。
Test
现在,xaml将在类ViewModelForTextBox
中查找WindowViewModel
属性,而不是在类Test
中找到ViewModelForTextBox
属性,而在binding will fail silently
类中找不到RelativeSource MarkupExtension
属性,{ {1}}并且不会查看Window的DataContext类。
如果您仍想为自定义UserControl设置DataContext但仍希望绑定到父级(Window)dataContext,则必须在绑定中使用<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}">
,如下所示 -
{{1}}
有关更多说明,请参阅MSDN文章here。
答案 1 :(得分:1)
你需要“查找”它的窗口祖先的datacontext。你的绑定看起来像这样:
<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">
答案 2 :(得分:1)
你应该发布你的SuperTextBox代码,因为你的错误。
通常你创建一个带有依赖项属性的usercontrol - 在你的情况下是“SuperValue” - 现在最重要的是你没有将SuperTextBox的datacontext设置为自己。
你必须在SuperTextBox中使用elementname绑定来绑定到“SuperValue”
<SuperTextBox x:Name="uc">
<TextBox Text="{Binding ElementName=uc, Path=SuperValue}/>
</superTextBox>
如果你这样做 - 你的
<local:SuperTextBox SuperValue="{Binding Test}"/>
应该可以工作,并且应该绑定到vm:WindowViewModel的Test属性。这就是唯一方式来编写如上所述的绑定。
编辑:如果你想为你的usercontrol创建一个viewmodel,那就说SuperTextViewmodel。然后它会有一个属性“SuperValue”。现在你不能设置datacontext两次所以我建议你必须在你的类型为SuperTextViewmodel的WindowView模型中添加一个属性,并处理你想要的属性。
你的绑定看起来像这样
<local:SuperTextBox DataContext="{Binding MySuperTextViewmodelInstanceOnWindowViewmodel}"/>
我会回答我的第一部分答案:)我总是说视图需要一个viewmodel但是一个usercontrol依赖属性。
答案 3 :(得分:1)
我觉得奇怪地回答了我的问题,但是...... 在我自己的控制下,我做了类似的事情:
<UserControl>
<Grid>
<Grid.DataContext>
<vm:UserControlViewModel />
</Grid.DataContext>
// here realy code of control
</Grid>
</UserControl>
现在我可以在控制和控制之外使用“自然”绑定。 :)