WPF - 如何在不干扰子UIElements的DataContext的情况下使用DataTrigger

时间:2013-10-12 01:23:17

标签: wpf xaml

我试图允许用户选择两种格式类型中的一种来输入double值,然后我想在xaml中使用DataTrigger来选择两种独立控件类型中的一种,供用户输入这些值,基于他们选择的格式。

我有一个视图和一个视图模型。视图模型具有以下属性:

public class MyViewModel
{
    public string DoubleFormat {get;set;}
    public double X {get;set;}
    public double Y {get;set;}
    public double Z {get;set;}
}

应用程序会将DoubleFormat属性设置为“FormatA”或“FormatB”,以便触发DataTrigger。

我的观点的xaml如下所示:

 <DataTemplate x:Key="FormatAEditTemplate" DataType="common:MyViewModel">
     <util:FormatAEditorControl Value="{Binding X}"/>
  </DataTemplate>

  <DataTemplate x:Key="FormatBEditTemplate" DataType="common:MyViewModel">
     <wpftk:DecimalUpDown Value="{Binding X}" />
  </DataTemplate>

  <DataTemplate x:Key="MyEditTemplate" DataType="common:MyViewModel">
     <ContentControl x:Name="MyDoubleInputControl" />
     <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding DoubleFormat}" Value="FormatA">
           <Setter TargetName="MyDoubleInputControl" Property="ContentTemplate" Value="    
             {StaticResource FormatAEditTemplate}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding DoubleFormat}" Value="FormatB">
           <Setter TargetName="MyDoubleInputControl" Property="ContentTemplate" Value="
             {StaticResource FormatBEditTemplate}" />
        </DataTrigger>
     </DataTemplate.Triggers>
  </DataTemplate>

因此,在触发器中,我实际上是尝试将ContentControl的ContentTemplate属性设置为等于顶部的两个模板值中的任何一个,从而呈现util:FormatAEditorControl或wpftk:DecimalUpDown,供用户编辑double值为视图模型上的属性X。

触发器执行工作,并且正确的控件类型 呈现,但输入控件本身的数据绑定不会工作。呈现控件但double属性没有“0.0”默认值,更新U / I中的属性也不会影响viewmodel属性值。当我打开大量的WPF输出日志记录时,我还在输出窗口中获得以下输出:

System.Windows.Data信息:41:BindingExpression路径错误:找不到'object'的'X'属性,因为数据项为null。这可能是因为数据提供者尚未生成任何数据。 BindingExpression:路径= X;的DataItem = NULL; target元素是'DecimalUpDown'(Name ='FooBar'); target属性为'Value'(类型'Nullable 1') System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=X; DataItem=null; target element is 'DecimalUpDown' (Name='FooBar'); target property is 'Value' (type 'Nullable 1') System.Windows.Data信息:21:BindingExpression无法从null数据项中检索值。当分离绑定或绑定到没有值的Nullable类型时,可能会发生这种情况。 BindingExpression:路径= X;的DataItem = NULL; target元素是'DecimalUpDown'(Name ='FooBar'); target属性为'Value'(类型'Nullable 1') System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=X; DataItem=null; target element is 'DecimalUpDown' (Name='FooBar'); target property is 'Value' (type 'Nullable 1')

......以及其他一些看似基本相同的行。

我可以简单地选择两种Control类型中的一种来“硬编码”到xaml中代替数据触发器,并且数据绑定正常工作,这使我怀疑设置DataTrigger的Binding属性是否干扰由触发器选择的“子”元素的DataContext。

那么我的问题是,因为我基本上希望整个视图中的每一件事都将MyViewModel作为其DataContext,有没有什么好办法让我的DataTrigger选择任何一种双输入控件类型而不会干扰他们的DataContexts?或者如果我从根本上误解了这种情况,那么也许有人可能会给我一个骨头。

一位优雅的同事通过以下方式绑定设法解决了这种情况: {Binding RelativeSource = {RelativeSource Mode = FindAncestor,AncestorType = {x:Type ContentControl}},Path = DataContext.X} 但这似乎是一个相当迂回的解决方法。

谢谢!

1 个答案:

答案 0 :(得分:1)

您正在使用ContentControl,因此模板化内容本质上是指其Content属性。根据您上面的描述,该属性未设置,因此绑定错误。

尝试将ContentControl设置为:

 <DataTemplate x:Key="MyEditTemplate" DataType="common:MyViewModel">
     <ContentControl x:Name="MyDoubleInputControl" Content="{Binding}" />

  ...

 </DataTemplate>