绑定依赖项属性为当前DataContext属性
我一直在努力使这一障碍在WPF中,我想我已经找到了解决办法,虽然难看。绑定依赖项属性为当前DataContext属性
的情况如下:
- 我有一个自定义依赖属性的自定义用户控件。
- 用户控件可以嵌套在我的其他用户控件内。
- 我的每个用户控件都有一个由定位器指定的数据上下文(我遵循MVVM模式)
- 我想将自定义依赖项属性绑定到父视图模型中的值。
代码...
父视图
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
</UserControl>
父类视图模型
public class ParentClassViewModel : BaseViewModel
{
private string _demoTextAlpha = "Some Alpha text";
public string DemoTextAlpha
{
get
{
return this._demoTextAlpha;
}
set
{
this._demoTextAlpha = value;
this.NotifyPropertyChange("DemoTextAlpha");
}
}
}
子视图
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ChildControlLocator}">
<TextBlock Text="{Binding Path=SomeProperty}" />
</UserControl>
儿童查看代码背后
public partial class Child : UserControl
{
public Child()
{
InitializeComponent();
}
public static readonly DependencyProperty DemoProperty =
DependencyProperty.Register("Demo",
typeof(string),
typeof(Child),
new FrameworkPropertyMetadata()
{
PropertyChangedCallback = OnDemoChanged,
BindsTwoWayByDefault = true
});
public string Demo
{
get { return this.GetValue(DemoProperty).ToString(); }
set { this.SetValue(DemoProperty, value); }
}
private static void OnDemoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (Child)d;
var viewModel = (ChildViewModel)control.DataContext;
viewModel.SomeProperty = (string)e.NewValue;
}
}
子视图模式
public class ChildViewModel : BaseViewModel
{
private string _someProperty;
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty = value;
this.NotifyPropertyChange("SomeProperty");
}
}
}
好了,所以这WORKS。我试图达到的是更好/更优雅的代码,特别是关于这个声明。
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
即使我能忍受,尽量优雅的推移,但有一点是困扰我现在的问题是,当我键入
Path=DataContext.DemoTextAlpha
当我尝试向下钻取智能感知下降在DataContext中。所以我必须格外小心地输入正确的东西。
那么 - 有什么不同的方式,使在DataContext的属性出现在智能感知,或者是有另一种方式来实现这一目标,我现在在做同样的事情?
谢谢。
EDIT到澄清
当我把这样的事情,而不是指定的相对源如在上述实施例...
<my:Child Demo="{Binding DemoTextAlpha}"/>
我收到错误...
System.Windows.Data Error: 40 : BindingExpression path error: 'DemoTextAlpha' property not found on 'object' ''ChildViewModel' (HashCode=34126977)'. BindingExpression:Path=DemoTextAlpha; DataItem='ChildViewModel' (HashCode=34126977); target element is 'Child' (Name=''); target property is 'Demo' (type 'String')
DataContext
的(与很多其它性能如FontSize
的沿)为沿视件树"Inherited"。因此这样的:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
</UserControl>
是完全一样的:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding DemoTextAlpha}"/>
</UserControl>
至于智能感知的支持,我不知道你使用的是什么版本的VS,但我使用VS 2010专业版与ReSharper的6.1,它增加了智能感知实现M如果指定d:DataContext
值:
<UserControl x:Class="...etc."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TheViewModelNamespace"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DataContext="{d:DesignInstance local:ViewModel}">
编辑:
确定..让我们analize你在这里做什么:
- 绑定用户控件到ParentVM:
ParentVM -> UserControl
- 使用的RelativeSource要从ParentVM中获取一些属性并将其放置到您在子控件中创建的自定义DP中
ParentVM -> UserControl -> Child Control
- 在自定义DP的OnPropertyChanged,同样的值设置为ChildVM
ParentVM -> UserControl -> Child Control -> ChildVM
你有没有意识到你正在使用的视图(用户控制,子控件)作为中间分享2视图模型之间的一些属性?你为什么不只是
ParentVM -> ChildVM
哪一个会更容易,更干净,真的MVVM?
要么从ParentVM直接引用ChildVM,要么使用类似于Messenger
模式的内容在它们之间进行间接通信。
的DataContext继承:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding DemoTextAlpha}" />
</UserControl>
如果伊娜不同的情况下,你的子控件都指定了不同的DataContext,你仍然需要绑定到父控件的DataContext
的属性,使用ElementName
可能更好:
<UserControl x:Name="Parent" DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, ElementName=Parent}" />
</UserControl>
请检查我的编辑到OP看到我的澄清...我试图把它放在评论中,但我无法正确格式化。 – imdandman 2013-04-08 16:44:44
@imdandman看到我的编辑。 – 2013-04-08 17:00:56
Drat!我忽略的另一件事。 你所说的是我一直在做的事情。我在构造函数中引用了其他虚拟机,当我需要填充数据时,我只是这样做了。 但是,当我需要将2x的ChildControl放置在同一父级中时,我遇到了此问题。那有意义吗? – imdandman 2013-04-08 17:05:08