DataTemplate в ControlTemplate не обновляет привязку - PullRequest
0 голосов
/ 16 ноября 2011

Я создал элемент управления с 3 PART_, одна PART_ изменяется в зависимости от типа, к которому он привязан, однако значения, измененные в Control, не обновляют привязку, похоже, она работает как привязка OneWay.Вот часть кода, который я считаю, имеет отношение:

<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 Path=Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}", шаблон не изменяется после установки.

Или есть лучший способ сделать это?

Спасибо

Ответы [ 2 ]

7 голосов
/ 26 октября 2012

Я только что столкнулся с той же проблемой, я хотел создать DataTemplate с DataType="{x:Type sys:Boolean}, у которого был только флажок.Но на этом пути было много предупреждающих знаков, говорящих мне, что это не так, как следует делать.

Сначала простое связывание {Binding} вызовет исключение " Двустороннее связываниетребуется путь или xpath", который был первым предупреждающим знаком.Я изменил привязку на {Binding .}, которая сработала (хотя в этой статье MSDN четко указано, что они эквивалентны).Тот факт, что вуду помогал, был вторым предупреждающим знаком.Затем он отображался правильно, и проверенное состояние соответствовало булевому значению, но при установке флажка (даже с UpdateSourceTrigger=PropertyChanged) он отказывался обновлять источник привязки, независимо от того, что я пробовал.Использование diagnostics:PresentationTraceSources.TraceLevel=High показало, что он даже не пытался выполнить привязку (третий предупреждающий знак).

Я продолжил и создал простую «коробку» для значения bool - класс с единственным свойством bool с именемValue с реализацией INotifyPropertyChanged.Я изменил привязку на {Binding Value}, и теперь все работает, включая двустороннюю привязку.

Вывод: Кажется, привязка не может обновить сам связанный объект, но только свойства этогообъект (именно поэтому {Binding} выдает исключение, но более явный {Binding .} подавляет это исключение, согласно ответу HB ).В любом случае, подход к созданию ViewModel и созданию шаблонов, нацеленных на него, представляется не просто руководством по проектированию, а действительным техническим требованием.

0 голосов
/ 16 ноября 2011

Я на самом деле никогда не работал с ContentTemplateSelector, но если бы мне пришлось рисковать, я бы сказал, что либо он не отвечает на PropertyChanged события в вашем свойстве ContentControl.Content, либо ваша привязка 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...