wpf 如何从 UserControl 访问父级的 DataContext
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6575180/
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
How to access parent's DataContext from a UserControl
提问by Cris
I need to access the container's DataContext from a UserControl (a grid containing textboxes and a listbox: I need to insert items in this list box) that I created in WPF: which is the best way to do it?
我需要从我在 WPF 中创建的 UserControl(一个包含文本框和列表框的网格:我需要在此列表框中插入项目)访问容器的 DataContext:这是最好的方法吗?
I was thinking to pass the DataContext as parameter to user control but think there is a cleaner way to do it.
我想将 DataContext 作为参数传递给用户控件,但认为有一种更简洁的方法来做到这一点。
回答by H.B.
Normally the DataContext
will be inherited, just do not explicitly set it on the UserControl
and it will get it from its parent. If you have to set it you could still use the Parent
property to get the parent, which you then can safe-cast to a FrameworkElement
and if it is not null you can grab its DataContext
.
通常DataContext
will 是继承的,只是不要在 上显式设置它UserControl
,它会从它的父级获取它。如果您必须设置它,您仍然可以使用该Parent
属性来获取父级,然后您可以将其安全转换为 a FrameworkElement
,如果它不为空,您可以获取它的DataContext
.
回答by Tod
I sometimes have nested User controls and a grandchild usercontrol sometimes needs the grandparent's view's data context. The easiest way I have found so far (and I'm somewhat of a newbie) is to use the following:
我有时嵌套用户控件,孙子用户控件有时需要祖父视图的数据上下文。到目前为止我发现的最简单的方法(而且我有点新手)是使用以下方法:
<Shared:GranchildControl DataContext="{Binding RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type GrandparentView}},
Path=DataContext.GrandparentViewModel}" />
I wrote up a more detailed exampleon my blog if you want more specifics.
回答by jv_
Add this BindingProxy class to your project:
将此 BindingProxy 类添加到您的项目中:
using System.Windows;
namespace YourNameSpace
{
/// <summary>
/// Add Proxy <ut:BindingProxy x:Key="Proxy" Data="{Binding}" /> to Resources
/// Bind like <Element Property="{Binding Data.MyValue, Source={StaticResource Proxy}}" />
/// </summary>
public class BindingProxy : Freezable
{
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy));
}
}
- Add the BindingProxy to your UserControl's resources.
- Set the 'Data' property of the BindingProxy to whatever you need, e.g. search for a parent Window.
Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}"
If you needed something more complex you could use a custom converter.
- 将 BindingProxy 添加到您的 UserControl 资源中。
- 将 BindingProxy 的“数据”属性设置为您需要的任何值,例如搜索父窗口。
Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}"
如果您需要更复杂的东西,您可以使用自定义转换器。
Now you have access to that parent's DataContext: {Binding Data.MyCommand, Source={StaticResource BindingProxy}}
现在您可以访问该父级的 DataContext: {Binding Data.MyCommand, Source={StaticResource BindingProxy}}
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:common="clr-namespace:YourNameSpace;assembly=YourAssembly"
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<common:BindingProxy x:Key="BindingProxy" Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}" />
</UserControl.Resources>
<Border>
<Button Command="{Binding Data.MyCommand, Source={StaticResource BindingProxy}}">Execute My Command</Button>
<!-- some visual stuff -->
</Border>
</UserControl>
回答by Gishu
H.B. answers the question in your title.
HB 回答您标题中的问题。
However the text poses a different design question. I'd ask you to reconsider your design.
然而,文本提出了一个不同的设计问题。我会请你重新考虑你的设计。
A control inherits the DataContext property of its ancestor as long as no one in between explicitly overrides.
If the user control needs data, it should get it from its data source (a viewmodel for the user control). So in this case, the user control can obtain the data it needs from the ListItemsForDisplay
property exposed on the SomeViewModel
instance. No need to get parent and cast.. much cleaner.
只要控件之间没有显式覆盖,控件就会继承其祖先的 DataContext 属性。
如果用户控件需要数据,它应该从它的数据源(用户控件的视图模型)获取它。所以在这种情况下,用户控件可以从实例ListItemsForDisplay
上公开的属性中获取它需要的数据SomeViewModel
。不需要让父母和演员......更干净。
<ContainerType DataSource={Binding SomeViewModel}>
<YourUserControl>
<ListBox ItemsSource={Binding ListItemsForDisplay}"/>
...