简体   繁体   中英

DataTemplate in ControlTemplate not updating Binding

I've created a control with 3 PART_s, one PART_ changes depending on the type bound to it, however values changed within the Control do not update the Binding, it seems to work as OneWay Binding.

Here's part of the code I beleive is relevant:

<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>

For Content I've also tried ... RelativeSource={RelativeSource AncestorType=local:DABaseControl} but no change.

If the DataTemplate Binding use "{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" the template doesn't change once set.

Or is there a better way to do this?

Thanks

I just encountered the same problem, I wanted to create a DataTemplate with DataType="{x:Type sys:Boolean} that just had a checkbox. But there were many warning signs along the way telling me this isn't the way it should be done.

At first, the simple binding of {Binding} would throw an exception " Two-way binding requires path or xpath ", which was the first warning sign. I changed the binding to {Binding .} which worked (even though this MSDN article clearly states that they're equivalent). That fact that voodoo was helping was the second warning sign. It then displayed correctly and the checked state was according to the boolean value, but when clicking the checkbox (even with UpdateSourceTrigger=PropertyChanged ), it refused to update the binding source, no matter what I tried. Using diagnostics:PresentationTraceSources.TraceLevel=High showed that it didn't even try to bind back (third warning sign).

I went ahead and created a simple "box" for the bool value - a class with a single bool property named Value with an INotifyPropertyChanged implementation. I changed the binding to {Binding Value} and now everything worked, including two way binding.

Conclusion: It seems a binding can't update the bound object itself, but only properties of that object (which is why {Binding} throws an exception, but the more explicit {Binding .} suppresses that exception, according to HB's answer ). In any case, the approach of creating a ViewModel and creating templates that target it appears to be more than a mere design guideline, but an actual technical requirement.

I've actually never worked with a ContentTemplateSelector , but if I had to hazard a guess I would say either it's not responding to PropertyChanged events on your ContentControl.Content property, or your Content binding is incorrect.

You can easily check if your binding is correct or not by removing the ContentTemplateSelector and seeing if data shows up at all. If it does, your binding is correct. If it doesn't, it's incorrect and you need to fix it.

If the problem is the ContentTemplateSelector , then I would suggest switching to a DataTrigger which determines which ContentTemplate to use based on the Content. This is what I usually do, and it uses a Converter which simply returns 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM