我的应用程序有一个MainWindow。在此范围内,有1个控件,ListBox
,绑定到MainWindowViewModel的属性。此属性是UserControl,类型为CriteriaVm
CriteriaVm有一个名为MyString
的字符串属性在Criteria View中我有以下代码
<UserControl x:Class="CompoundInterests.View.CriteriaView"
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:vm="clr-namespace:CompoundInterests.ViewModel"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600">
<UserControl.Resources>
<ResourceDictionary Source="../Dictionary.xaml" />
</UserControl.Resources>
<Grid>
<Border>
<Expander Header="{Binding MyString}" >
<vm:PropertiesVm ThresholdName="{Binding MyString}" />
</Expander>
</Border>
</Grid>
</UserControl>
正如你所看到的,我在两个地方绑定了MyString。扩展器中的绑定工作正常,vm中的绑定:PropertiesVm没有(使用Dependency Properites)。输出窗口中显示以下错误
System.Windows.Data错误:2:找不到目标元素的管理FrameworkElement或FrameworkContentElement。 BindingExpression:路径= MyString中;的DataItem = NULL; target元素是'PropertiesVm'(HashCode = 5991653); target属性是'ThresholdName'(类型'String')
确定错误消息告诉我它在ProperitesVm中寻找MyString ...我应该在CriteriaVm中寻找MyString。这意味着我需要使用RelativeSource,我认为它是1级和UserControl类型。所以我更新到:
<vm:PropertiesVm ThresholdName="{Binding Path=MyString, RelativeSource={RelativeSource AncestorLevel=1,AncestorType=UserControl,Mode=FindAncestor}}" />
我得到一个稍微不同的问题,但看起来好像存在相同的潜在错误
System.Windows.Data错误:4:无法找到与引用'RelativeSource FindAncestor绑定的源,AncestorType ='System.Windows.Controls.UserControl',AncestorLevel ='1''。 BindingExpression:路径= MyString中;的DataItem = NULL; target元素是'PropertiesVm'(HashCode = 24649639); target属性是'ThresholdName'(类型'String')
目前,PropertiesVm只有依赖属性,PropertiesView只是一个空网格。这样我就可以先处理这个错误,然后再担心下一个绑定阶段。
我不明白为什么我收到错误消息或者我做错了什么。 如果需要,我可以愉快地提供更多代码。这个阶段的项目很早,因此是最少的代码。
答案 0 :(得分:1)
我希望视图看起来像这样:
<Style TargetType="{x:Type ns:YourViewModel}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ns:YourViewModel}">
<Grid>
<TextBlock Text="{Binding ThresholdName,
RelativeSource={RelativeSource TemplatedParent}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
视图模型代码与您所显示的内容几乎没有变化:
public class YourViewModel: Control
{
public static readonly DependencyProperty ThreshNameProperty = DependencyProperty.Register("ThresholdName", typeof(string), typeof(PropertiesVm), new PropertyMetadata(string.Empty));
public string ThresholdName
{
get { return GetValue(ThreshNameProperty).ToString(); }
set { SetValue(ThreshNameProperty, value); }
}
}
你并不完全清楚&#34; MyStringValue&#34;是的,我希望它是MainWindow的正常属性。 MainWindow会创建一个控件实例,设置&#34; ThresholdName&#34;对此&#34; MyStringValue&#34;属性:
<Grid>
<ns:YourViewModel ThresholdName="{Binding MyStringValue}"/>
</Grid>
最后你的MainWindow代码是:
public string MyStringValue { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyStringValue = "dog";
}
答案 1 :(得分:1)
答案在信息中!
System.Windows.Data错误:2:找不到目标元素的管理FrameworkElement或FrameworkContentElement。 BindingExpression:路径= MyString中;的DataItem = NULL;目标元素是&#39; PropertiesVm&#39; (的HashCode = 5991653);目标属性是'ThresholdName&#39; (键入&#39; String&#39;)
根据我的理解,因为我的UserControl继承了DependencyObject而不是UserControl它不是UIElement ......
因此,我不得不将依赖属性移动到我的View的代码隐藏,这允许双向绑定工作,但在ViewModel中保留了我的ViewModel的datacontext。
答案 2 :(得分:1)
如果您将继承从DependencyObject更改为FrameworkElement,则应该可以。
<vm:PropertiesVm DataContext="{Binding}" ThresholdName="{Binding MyString}" />
无论如何,你有没有试过附属物?
我猜这一个是这样或那样的。