wpf 通过 MVVM 模式创建 UserControl - DataContext 并绑定到父级

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12993908/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 05:52:15  来源:igfitidea点击:

Creating UserControl via MVVM pattern - DataContext and binding to parent

c#wpfmvvmbindinguser-controls

提问by Never

I use MVVM pattern so my own control contains View and ViewModel.
ViewModel is connected with View by DataContext property. This makes problems with binding. Why?

我使用 MVVM 模式,所以我自己的控件包含 View 和 ViewModel。
ViewModel 通过 DataContext 属性与 View 相连。这会给绑定带来问题。为什么?

Assume this situation:
I created new user control - for example - "SuperTextBox". It have a property "SuperValue".
And now I do something like that:

假设这种情况:
我创建了新的用户控件 - 例如 - “SuperTextBox”。它有一个属性“SuperValue”。
现在我做这样的事情:

<Window>
    <Window.DataContext>
        <vm:WindowViewModel/>
    </Window.DataContext>

    <local:SuperTextBox SuperValue="{Binding Test}"/>
</Window>

I thought that "binding process" joins SuperTextBox.SuperValue with Window.DataContext.Test, but no, 'binding process" joins SuperTextBox.SuperValue with SuperTextBox.DataContext.Test what is for me unnatural and misleading.

我认为“绑定过程”将 SuperTextBox.SuperValue 与 Window.DataContext.Test 连接起来,但不,“绑定过程”将 SuperTextBox.SuperValue 与 SuperTextBox.DataContext.Test 连接起来,这对我来说是不自然的和误导性的。

Other controls like "TextBox" I can use in above way because they do not have their DataContext.

其他控件,如“TextBox”,我可以以上述方式使用,因为它们没有 DataContext。

How can I use MVVM pattern to creating UserControls keeping natural binding (to DataContext of parent control) ?

如何使用 MVVM 模式来创建保持自然绑定(到父控件的 DataContext)的用户控件?

Edit:

编辑:

I got many answers how binding to parent, but I know this earlier. The problem is - how can I create UserControl via MVVM patern (having ViewModel) and stay natural binding - default to parent DataContext.

我得到了很多关于如何绑定到父母的答案,但我更早知道这一点。问题是 - 如何通过 MVVM 模式(具有 ViewModel)创建 UserControl 并保持自然绑定 - 默认为父 DataContext。

I want to have ViewMoldel and still can binding like this:

我想要 ViewMoldel 并且仍然可以像这样绑定:

<local:SuperTextBox SuperValue="{Binding Test}"/>

Is it possible?

是否可以?

采纳答案by Never

I feel oddly answering on my question but...
In my own control i did something like that:

我对我的问题回答很奇怪,但是......
在我自己的控制下,我做了这样的事情:

<UserControl>
    <Grid>
        <Grid.DataContext>
             <vm:UserControlViewModel />
        </Grid.DataContext>
        // here realy code of control
    </Grid>
</UserControl>

Now I can use "natural" binding outside of control and in control. :)

现在我可以使用不受控制和受控制的“自然”绑定。:)

回答by Rohit Vats

All bindings applied on any control always first look for the binding in its DataContext. In case the DataContext is not set for the control, then it walks up the Visual Treeupto its parent unless it finds the DataContext.

应用于任何control always first look for the binding in its DataContext. 如果未为控件设置 DataContext,则它一直walks up the Visual Tree到其父级,除非它找到 DataContext。

Even if you set the DataContexton your textBox to some value different than of Window's DatContext, it will always search for property Teston that particular DataContext and not on your Window's DataContext.

即使您将DataContexttextBox 上的设置为与 Window 的 DatContext 不同的某个值,它也将始终搜索Test该特定 DataContext 上的属性,而不是您的Window's DataContext.

<TextBox>
   <TextBox.DataContext>
      <vm:ViewModelForTextBox/>
   </TextBox.DataContext>
   <TextBox.Text>
      <Binding Path="Test"/>
   </TextBox.Text>
</TextBox>

Now, xaml will look for Testproperty in class ViewModelForTextBoxinstead in class WindowViewModeland if Testproperty is not found in class ViewModelForTextBox, binding will fail silentlyand won't look up to the Window's DataContext class.

现在,xaml 将Test在 class 中ViewModelForTextBox而不是在 class 中查找属性,WindowViewModel如果Test在 class 中找不到属性ViewModelForTextBoxbinding will fail silently则不会查找 Window 的 DataContext 类。

In case you still want to set the DataContext for your Custom UserControl but still want to bind to the parent's (Window) dataContext, you have to use the RelativeSource MarkupExtensionin your bindings like this -

如果您仍想为自定义 UserControl 设置 DataContext 但仍想绑定到父级的(Window)dataContext,则必须RelativeSource MarkupExtension像这样在绑定中使用-

<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test,
                                RelativeSource={RelativeSource Mode=FindAncestor,
                                                 AncestorType={x:Type Window}}}">

Refer to the MSDN article herefor more clarification.

有关更多说明,请参阅此处的 MSDN 文章。

回答by blindmeis

you should post your SuperTextBox code, because there is your error.

你应该发布你的 SuperTextBox 代码,因为有你的错误。

usually you create a usercontrol with a dependency property - in your case "SuperValue" - and now the most important thing you do not set the datacontext of your SuperTextBox to it self.

通常你会创建一个具有依赖属性的用户控件——在你的例子中是“SuperValue”——现在最重要的是你不要将 SuperTextBox 的数据上下文设置为它自己。

you have to use elementname binding within your SuperTextBox to bind to "SuperValue"

您必须在 SuperTextBox 中使用 elementname 绑定来绑定到“SuperValue”

 <SuperTextBox x:Name="uc">
   <TextBox Text="{Binding ElementName=uc, Path=SuperValue}/>
 </superTextBox>

if you do this that way - your

如果你这样做 - 你的

 <local:SuperTextBox SuperValue="{Binding Test}"/>

should work and should bind to the Test Property of your vm:WindowViewModel. thats the onlyway to write the binding like above.

应该可以工作并且应该绑定到您的 vm:WindowViewModel 的测试属性。这是编写上述绑定的唯一方法。

EDIT: if you wanna create a viewmodel for your usercontrol, let say SuperTextViewmodel. then it would have a property "SuperValue". now you cant set the datacontext twice so i would suggest you have to add a Property to your WindowViewmodel of type SuperTextViewmodel and handle the properties like you want.

编辑:如果你想为你的用户控件创建一个视图模型,比如说 SuperTextViewmodel。那么它就会有一个属性“SuperValue”。现在你不能设置 datacontext 两次所以我建议你必须向你的 WindowViewmodel 添加一个属性到你的 SuperTextViewmodel 类型并处理你想要的属性。

your binding the looks like this

你的绑定看起来像这样

 <local:SuperTextBox DataContext="{Binding MySuperTextViewmodelInstanceOnWindowViewmodel}"/>

i would go with my first part of the answer :) i always say a view need a viewmodel but a usercontrol dependency properties.

我会回答我的第一部分:) 我总是说一个视图需要一个视图模型,但需要一个用户控件依赖属性。

回答by Lee O.

You need to "Look up" the datacontext of it's window ancestor. Your binding would look like this:

您需要“查找”其窗口祖先的数据上下文。您的绑定将如下所示:

<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}">