wpf 一个控件的多个数据上下文 - MVVM
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15498890/
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
Multiple dataContext for one control - MVVM
提问by Ofir
I am not sure if my question header represent exactly my problem, I will do the best to explain:
我不确定我的问题标题是否完全代表我的问题,我会尽力解释:
I have a grid cell DataTemplate: (the grid belong to third party company but it`s not important for my question)
我有一个网格单元 DataTemplate:(网格属于第三方公司,但对我的问题并不重要)
<DataTemplate>
<TextBlock>
<Hyperlink Command="{Binding OpenLinkCommand}">
<Hyperlink.ToolTip>
<TextBlock Text="{Binding Data.MapLink}"/>
</Hyperlink.ToolTip>
<TextBlock Text="{Binding Data.MapLink}" TextDecorations="underline">
</Hyperlink>
</TextBlock>
</DataTemplate>
I want make this DataTemplate to show some hyperlink ("Data.MapLink" is the object which contain the link value) and each click on this link will fire the command "OpenLinkCommand".
我想让这个 DataTemplate 显示一些超链接(“Data.MapLink”是包含链接值的对象),每次点击这个链接都会触发命令“OpenLinkCommand”。
The problem is that "Data.MapLink" and "OpenLinkCommand" are located in different dataContext and then I have to choose one of the next choices:
问题是“Data.MapLink”和“OpenLinkCommand”位于不同的数据上下文中,然后我必须选择下一个选项之一:
leave hyperlink dataContext as it - the command won`t work and the hyperlink will get the Data.MapLink value.
change hyperlink dataContext to the command datacontext - The command will work but the hyperlink name will be empty.
保持超链接 dataContext 不变 - 该命令将不起作用,超链接将获得 Data.MapLink 值。
将超链接 dataContext 更改为命令 datacontext - 该命令将起作用,但超链接名称将为空。
Regretfully I don`t have option put those items in same dataContext so I must find a way how to tell the command that it dataContext is "X" and tell the hyperLink that it dataContext is "Y".
遗憾的是,我没有选择将这些项目放在同一个 dataContext 中,所以我必须找到一种方法来告诉命令它的 dataContext 是“X”并告诉超链接它的 dataContext 是“Y”。
I am hoping that my question is clear How can I solve this problem?
我希望我的问题很清楚我该如何解决这个问题?
回答by Rachel
There are some binding properties you can use to specify a different Sourcefor your binding than the default DataContext
有一些绑定属性可以用来Source为你的绑定指定一个不同于默认值的绑定属性DataContext
The most common ones are ElementNameor RelativeSource, which will find another UI element in the VisualTree so you can bind to it's properties.
最常见的是ElementNameor RelativeSource,它会在 VisualTree 中找到另一个 UI 元素,以便您可以绑定到它的属性。
For example, the following uses ElementNameto tell the binding that it should use MyGridViewas the binding source, and to bind to MyGridView.DataContext.OpenLinkCommand
例如,以下用于ElementName告诉绑定它应该MyGridView用作绑定源,并绑定到MyGridView.DataContext.OpenLinkCommand
<Hyperlink Command="{Binding ElementName=MyGridView,
Path=DataContext.OpenLinkCommand}">
You can also use RelativeSourcein a binding to find an object further up the VisualTree of the specified object type, and use it as the binding source. This example does the same thing as the above example, except it uses RelativeSourceinstead of ElementName, so your GridViewdoesn't need to have a Namespecified.
您还可以RelativeSource在绑定中使用以在指定对象类型的 VisualTree 上进一步查找对象,并将其用作绑定源。这个例子与上面的例子做同样的事情,除了它使用RelativeSource代替ElementName,所以你GridView不需要Name指定。
<Hyperlink Command="{Binding
RelativeSource={RelativeSource AncestorType={x:Type GridView}},
Path=DataContext.OpenLinkCommand}">
A third option is to set the binding's Sourceproperty to a static object, like this:
第三个选项是将绑定的Source属性设置为静态对象,如下所示:
<Hyperlink Command="{Binding
Source={x:Static local:MyStaticClass.OpenLinkCommand}}">
Based on your comment hereabout binding to a singleton, this would probably be the best option for you.
回答by Backlash
You will have to have an instance of the desired data context (usually in the resources of a control or window). Once you have that, you should be able to explicitly set the data context of the textblock instead of inheriting the parent data context automatically.
您必须拥有所需数据上下文的实例(通常在控件或窗口的资源中)。一旦你有了它,你应该能够显式设置文本块的数据上下文,而不是自动继承父数据上下文。
For example:
例如:
<TextBlock DataContext="{StaticResource MyDataMapLinkDataContext}" Text="{Binding Data.MapLink}" TextDecorations="underline"/>
回答by Andy
If you really do need to use another property for an extra data context then you can just use an attached property.
如果您确实需要为额外的数据上下文使用另一个属性,那么您可以只使用附加属性。
XAML
XAML
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{Binding (local:ExtraDataContextProvider.ExtraDataContext), RelativeSource={RelativeSource TemplatedParent}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Button Margin="172,122,131,79" Foreground="Green" local:ExtraDataContextProvider.ExtraDataContext="A test">
test
</Button>
</Grid>
</Window>
Code
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication1
{
public class ExtraDataContextProvider : DependencyObject
{
public static object GetExtraDataContext(DependencyObject obj)
{
return (object)obj.GetValue(ExtraDataContextProperty);
}
public static void SetExtraDataContext(DependencyObject obj, object value)
{
obj.SetValue(ExtraDataContextProperty, value);
}
public static readonly DependencyProperty ExtraDataContextProperty = DependencyProperty.RegisterAttached("ExtraDataContext", typeof(object), typeof(ExtraDataContextProvider), new PropertyMetadata(null));
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}

