【问题标题】:WPF - How to use DataTrigger without interfering with DataContext of child UIElementsWPF - 如何在不干扰子 UIElements 的 DataContext 的情况下使用 DataTrigger
【发布时间】:2013-10-20 04:50:39
【问题描述】:

我试图允许用户选择两种格式类型之一来输入双精度值,然后我想在 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 供用户编辑双精度值视图模型上的属性 X。

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

System.Windows.Data 信息:41:BindingExpression 路径错误:找不到“对象”的“X”属性,因为数据项为空。这可能是因为数据提供者尚未生成任何数据。绑定表达式:路径=X;数据项=空;目标元素是'DecimalUpDown'(名称='FooBar');目标属性是“值”(类型“Nullable1') 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 'Nullable1”) System.Windows.Data 信息:21:BindingExpression 无法从空数据项中检索值。当绑定分离或绑定到没有值的 Nullable 类型时,可能会发生这种情况。绑定表达式:路径=X;数据项=空;目标元素是'DecimalUpDown'(名称='FooBar');目标属性是“值”(类型“Nullable1') 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 'Nullable1”)

...以及其他几行似乎基本相同的内容。

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

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

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

谢谢!

【问题讨论】:

    标签: wpf xaml


    【解决方案1】:

    您正在使用 ContentControl,因此模板化内容本质上是指其 Content 属性。从您上面写的内容来看,该属性未设置,因此存在绑定错误。

    尝试将 ContentControl 设置为:

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

    【讨论】:

    • 没错。谢谢。我也刚刚发现了这个stackoverflow.com/questions/4480388/…。在我目前的经验水平上,这个特殊问题感觉像是一个令人讨厌的问题,但这可能只是幼稚。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 2021-09-26
    相关资源
    最近更新 更多