【问题标题】:DataTemplate in ControlTemplate not updating BindingControlTemplate 中的 DataTemplate 未更新绑定
【发布时间】:2011-12-30 11:07:09
【问题描述】:

我创建了一个包含 3 个 PART_s 的控件,其中一个 PART_ 会根据绑定到它的类型而变化,但是在控件内更改的值不会更新绑定,它似乎作为单向绑定工作。

这是我认为相关的部分代码:

<DataTemplate x:Key="BooleanDAView" DataType="{x:Type sys:Boolean}">
    <CheckBox IsChecked="{Binding ., Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate x:Key="DateTimeDAView" DataType="{x:Type sys:DateTime}">
    <extToolkit:DateTimePicker Value="{Binding ., Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate x:Key="Int32DAView"  DataType="{x:Type sys:Int32}">
    <extToolkit:IntegerUpDown Value="{Binding ., Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate x:Key="StringDAView"  DataType="{x:Type sys:String}">
    <TextBox Text="{Binding ., Mode=TwoWay}"/>
</DataTemplate>

....

<ContentControl x:Name="PART_Content"
        Grid.Row="0" Grid.Column="1"
        Margin="{TemplateBinding Padding}"
        VerticalAlignment="Center"
        VerticalContentAlignment="Center"
        Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
        >
    <ContentControl.ContentTemplateSelector>
        <controls:TypeBasedDataTemplateSelector>
            <controls:TypeBasedDataTemplateSelector.Templates>
                <controls:TypedDictionary>
                    <sys:String x:Key="{x:Type sys:Boolean}">BooleanDAView</sys:String>
                    <sys:String x:Key="{x:Type sys:DateTime}">DateTimeDAView</sys:String>
                    <sys:String x:Key="{x:Type sys:Int32}">Int32DAView</sys:String>
                    <sys:String x:Key="{x:Type sys:String}">StringDAView</sys:String>
                </controls:TypedDictionary>
            </controls:TypeBasedDataTemplateSelector.Templates>
        </controls:TypeBasedDataTemplateSelector>
    </ContentControl.ContentTemplateSelector>
</ContentControl>

对于内容,我也尝试过...RelativeSource={RelativeSource AncestorType=local:DABaseControl},但没有变化。

如果 DataTemplate Binding 使用"{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}",则模板一旦设置就不会改变。

或者有更好的方法吗?

谢谢

【问题讨论】:

    标签: c# wpf xaml binding


    【解决方案1】:

    我刚刚遇到了同样的问题,我想用只有一个复选框的DataType="{x:Type sys:Boolean} 创建一个DataTemplate。但是一路上有很多警告信号告诉我这不是应该的方式。

    起初,{Binding} 的简单绑定会抛出异常“双向绑定需要路径或 xpath”,这是第一个警告信号。我将绑定更改为{Binding .},它有效(尽管this MSDN article 明确声明它们是等效的)。巫毒教正在帮助的事实是第二个警告信号。然后它正确显示并且选中状态根据布尔值,但是当单击复选框时(即使使用UpdateSourceTrigger=PropertyChanged),无论我尝试什么,它都拒绝更新绑定源。使用diagnostics:PresentationTraceSources.TraceLevel=High 表明它甚至没有尝试绑定回来(第三个警告标志)。

    我继续为 bool 值创建了一个简单的“框” - 一个具有单个 bool 属性的类,名为 Value 和一个INotifyPropertyChanged 实现。我将绑定更改为{Binding Value},现在一切正常,包括双向绑定。

    结论:似乎绑定不能更新绑定对象本身,而只能更新该对象的属性(这就是为什么{Binding} 会抛出异常,但更明确的{Binding .} 会抑制那个例外,根据H.B.'s answer)。无论如何,创建 ViewModel 和创建针对它的模板的方法似乎不仅仅是一个设计指南,而是一个实际的技术要求。

    【讨论】:

      【解决方案2】:

      我实际上从未使用过ContentTemplateSelector,但如果我不得不冒险猜测,我会说它没有响应您的ContentControl.Content 属性上的PropertyChanged 事件,或者您的Content 绑定不正确.

      您可以通过删除ContentTemplateSelector 并查看数据是否显示来轻松检查您的绑定是否正确。如果是这样,则您的绑定是正确的。如果没有,那就是不正确的,你需要修复它。

      如果问题是ContentTemplateSelector,那么我建议切换到DataTrigger,它根据内容确定要使用哪个ContentTemplate。这是我通常做的,它使用一个只返回typeof(value)的转换器

       <Style TargetType="{x:Type ContentControl}">
           <Setter Property="ContentTemplate" Value="{StaticResource StringDAView}" />
           <Style.Triggers>
               <DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}" 
                            Value="{x:Type sys:Boolean">
                   <Setter Property="ContentTemplate" Value="{StaticResource BooleanDAView}" />
               </DataTrigger>
               <DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}" 
                            Value="{x:Type DateTime">
                   <Setter Property="ContentTemplate" Value="{StaticResource DateTimeDAView}" />
               </DataTrigger>
               <DataTrigger Binding="{Binding Converter={StaticResource ObjectToTypeConverter}" 
                            Value="{x:Type sys:Int32">
                   <Setter Property="ContentTemplate" Value="{StaticResource Int32DAView}" />
               </DataTrigger>
           </Style.Triggers>
       </Style>
      

      【讨论】:

      • ContentTemplateSelector 确实显示了正确的值和表示形式,如果它的绑定属性发生更改,显示的值将更新(行为类似于 OneWay),但如果使用说 @ 更改值987654333@ 显示在控件内,它不会更新绑定的属性。我也尝试了 DataTrigger 方法,但结果相似。
      • @user1049761 我猜这与您将Content 属性绑定到模板的Content 值有关。我不确定出了什么问题,因为我看不到包含ContentControlTemplate,但是尝试绑定到{TemplateBinding DataContext} 而不是{TemplateBinding Content}
      • 谢谢让我朝着正确的方向前进,现在我需要弄清楚究竟是什么解决了这个问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-14
      • 2012-11-10
      • 1970-01-01
      • 2017-10-29
      • 2011-04-21
      相关资源
      最近更新 更多