【发布时间】:2011-07-04 19:00:49
【问题描述】:
我需要从我在 WPF 中创建的 UserControl(包含文本框和列表框的网格:我需要在此列表框中插入项目)访问容器的 DataContext:这是最好的方法吗?
我正在考虑将 DataContext 作为参数传递给用户控件,但认为有一种更简洁的方法。
【问题讨论】:
标签: wpf user-controls datacontext
我需要从我在 WPF 中创建的 UserControl(包含文本框和列表框的网格:我需要在此列表框中插入项目)访问容器的 DataContext:这是最好的方法吗?
我正在考虑将 DataContext 作为参数传递给用户控件,但认为有一种更简洁的方法。
【问题讨论】:
标签: wpf user-controls datacontext
【讨论】:
DataContexts,我想我以前可能做过类似的事情。
有时我有嵌套的用户控件,而孙子用户控件有时需要祖父视图的数据上下文。到目前为止,我发现的最简单的方法(而且我有点新手)是使用以下方法:
<Shared:GranchildControl DataContext="{Binding RelativeSource={RelativeSource
FindAncestor, AncestorType={x:Type GrandparentView}},
Path=DataContext.GrandparentViewModel}" />
如果您想了解更多详情,我在我的博客上写了more detailed example。
【讨论】:
将此 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));
}
}
Data="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}},Path=DataContext}" 如果您需要更复杂的东西,您可以使用自定义转换器。现在您可以访问该父级的 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>
【讨论】:
H.B.回答标题中的问题。
但是,文本提出了不同的设计问题。我会请你重新考虑你的设计。
只要中间没有人显式覆盖,控件就会继承其祖先的 DataContext 属性。
如果用户控件需要数据,它应该从其数据源(用户控件的视图模型)中获取数据。因此在这种情况下,用户控件可以从SomeViewModel 实例上公开的ListItemsForDisplay 属性中获取所需的数据。无需让父母和演员..更清洁。
<ContainerType DataSource={Binding SomeViewModel}>
<YourUserControl>
<ListBox ItemsSource={Binding ListItemsForDisplay}"/>
...
【讨论】:
在这种情况下,UserControl 将获得 DataContext 窗口
<Window>
<local:MyUserControl DataContext="{Binding}"/>
</Window>
【讨论】: