2013-03-21 4 views
1

Я использую DataTemplateSelector внутри ContentControl. У меня 3 разных DataTemplates на основе 3 разных object types. Когда я устанавливаю из моих ContentControl в данные указанных типов, DataTemplateSelector свопирует к определенному DataTemplate И, наоборот, селектор, похоже, откатывает/перезапускает значения из старого шаблона. Почему это так?DataTemplateSelector и его странное поведение

Edit: Я понял, что значения получают сброшены, потому что у меня есть вложенное свойство caled Prop и внутри его OnPropertyChangedCallback он уведомляет меня о Prop, имеющий нулевое значение на обмен между DataTemplates. Вы можете увидеть это прикрепленное свойство в коде ниже.

Может кто-нибудь помочь мне в том, что происходит за этим механизмом обмена DataTemplateSelector?

Вот глубже объяснений с кодом:

public void Window1() 
{ 
    InitalizeComponents(); 
} 

public void OnClick(object sender, RoutedEventArgs e) 
{ 
    if(this.DataContext == null) 
    this.DataContext = "Hallo"; 
else{ 
    if(this.DataContext is string) 
    this.DataContext = 123; 
    else{ 
    if(this.DataContext is int) 
    this.DataContext = null; 
    } 
    } 
} 
By clicking on Button few times I change the type and so in ContentControl the selector changes to DataTemplate. 

Селектор выглядит следующим ниже. Он меняет местами между textDataTemplate и numericDataTemplate и еще одним шаблоном. Как я уже упоминал, у меня есть те три типа, которые являются string, int, and one more, что я не хочу отмечать. Их DataTemplates называются textDataTemplate, numericDataTemplate и еще один. :)

<local:MyTemplateSelector x:Key="dataTemplateSelector" 
           TextTemplate="{StaticResource textDataTemplate}" 
           NumericTemplate="{StaticResource numericDataTemplate}"/> 

public class MyTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate TextTemplate; 

    public DataTemplate NumericTemplate; 


    public DataTemplate Select(object item, Culture.....) 
    { 
    if(item is string) 
    { 
     return this.TextTemplate; 
    } 
    else 
    { 
     return this.NumericTemplate; 
    } 
    } 
} 

ContentControl и XAML выглядит следующим образом:

<Button Click="OnClick" Content="Click Me"/> 


<ContentControl Name="contentCtrl" 
       Content="{Binding}" 
       Width="123" 
       ContentTemplateSelector="{StaticResource dataTemplateSelector}" /> 

И это, как textDataTemplate выглядит так.

<DataTemplate x:Key="textDataTemplate"> 
    <TextBox x:Name="text" my:AttProperties.Prop="{extension:MarkupExt value}" Text="{Binding Path=Txt, Mode=Default, UpdateSourceTrigger=Explicit}"/> 
</DataTemplate> 

numericDataTemplate похож на textDataTemplate всего, что только цифры разрешены.

Prop является моим attached property от AttProperties class от type string. Prop находится где-то внутри всех трех DataTemplate. Над Prop сидит на TextBox, но это может быть и Label. markupextension - всего лишь "return Hello". Расширение просто для проверки того, как создать пользовательское расширение разметки. Нет большой сделки с расширением. Это не должно многое сделать с заменой DataTemplates.

Еще один раз, чтобы объяснить мою проблему. Swapping, похоже, перепродает/откатывает старые шаблоны. Я заменяю textDataTemplate, чтобы сказать, что numericDataTemplate и Prop of textDataTemplate получает значение null, но значение before было «Hello».

Почему это происходит? Похоже, что с использованием tiggers. Как только Trigger недействителен, он откатывает использованные значения. Является DataTemplateSelector, используя какой-то такой же механизм, как Triggers?

Edited: Прилагаемый свойство только простой .RegisterAttached с OnPropertyChangedCallback. Внутри OnPropertyChangedCallback я понял, что prop имеет значение null при замене dataTemplates.

+0

Есть ли у вас какие-либо конкретные проблемы или это просто хочу знать "вопрос? – DHN

+0

Можете ли вы разместить шаблон и посмотреть, пожалуйста? ИМХО Я не думаю, что «Шаблон» воссоздается снова и снова. – DHN

+0

Я отредактировал мой вопрос с кодом и более объяснением. –

ответ

3

Если вы используете двустороннюю привязку в числовом шаблоне, и оно принимает только что-то вроде Double, оно может установить значение в число. Но никто не может быть уверен, не видя полного кода. Возможно, ваш собственный код делает что-то неправильно. Чтобы лучше понять ситуацию, создайте свой собственный элемент управления, полученный из ContentControl, и используйте его в своем примере. Затем переопределите методы управления OnContentxxxChanged, вставьте точки останова и отлаживайте приложение. Вы должны понимать, что происходит с вашими данными и с помощью селектора шаблонов. Когда приложение останавливается в точке останова, тщательно проверьте все значения и посмотрите на трассировку стека. Чтобы отлаживать привязки, вы можете вставить IValueConverters, это даст вам место в коде, где вы можете проверить значения.

Я действительно предлагаю вам сначала сделать простейшую рабочую вещь, а затем перейти к более сложным вещам, таким как текстовые поля с двусторонними привязками к некоторому свойству некоторого элемента управления, которого вы не показывали в своем вопросе. Вот рабочая версия с TextBlocks:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
    public void OnClick(object sender, RoutedEventArgs e) 
    { 
     if (this.DataContext == null) 
      this.DataContext = "Hallo"; 

     else if (this.DataContext is string) 
      this.DataContext = 123; 

     else if (this.DataContext is int) 
      this.DataContext = null; 
    } 
} 
public class MyTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate TextTemplate {get; set;} 

    public DataTemplate NumericTemplate {get; set;} 

    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     if (item is string) 
     { 
      return this.TextTemplate; 
     } 
     else 
     { 
      return this.NumericTemplate; 
     } 
    } 
} 

и XAML:

<Grid> 
    <Grid.Resources> 
     <DataTemplate x:Key="numericDataTemplate"> 
      <TextBlock Foreground="Red" Text="{Binding}" /> 
     </DataTemplate> 
     <DataTemplate x:Key="textDataTemplate"> 
      <TextBlock Foreground="Green" Text="{Binding}"/> 
     </DataTemplate> 
     <local:MyTemplateSelector x:Key="dataTemplateSelector" 
          TextTemplate="{StaticResource textDataTemplate}" 
          NumericTemplate="{StaticResource numericDataTemplate}"/> 
    </Grid.Resources> 
    <StackPanel> 
     <Button Click="OnClick" Content="Click Me" VerticalAlignment="Top"/> 
     <ContentControl Name="contentCtrl" 
       Content="{Binding}" 
       Width="300" Height="100" 
       ContentTemplateSelector="{StaticResource dataTemplateSelector}" /> 
     </StackPanel> 
</Grid> 

Сравнить с кодом. Когда вы наследуете DataTemplateSelector, вы должны переопределить метод SelectTemplate и не изобретать методы с другими именами. Все элементы управления, такие как ContentControl, будут использовать только SelectTemplate. Etc ..

Очевидно, что все работы и DataTemplateSelector не делают ничего плохого. Я полагаю, ваша проблема где-то в ваших данных и привязок

И посмотреть на ваш метод OnClick - это всегда устанавливает DataContext обнулить

+0

извините, но я не знаю, о чем вы говорите .. больше нет кода, чтобы показать .. его действительно простое приложение .. Мне жаль, что я не могу показать вам больше кода, но нет. Я не создаю и не настраиваю что-то свое. все чистые wpf и xaml –

+1

извините, в вашем вопросе я вообще не вижу никакого кода о том, что вы используете в качестве DataContext или как его изменить. Из ваших фрагментов вы не можете восстановить свое приложение и запустить его. Здесь нет телепатии. – notacat

+0

Я отредактировал код. Взгляни, пожалуйста. –

Смежные вопросы