2016-04-26 3 views
0

У меня есть UserControl, в котором ключ визуальный элемент представлено следующим образом:Связывание с UserControl DataContext: обновление ContentTemplateSelector, когда некоторые свойства изменяются

<ContentPresenter Content="{Binding}" 
    ContentTemplateSelector="{StaticResource MStatusDisplaySelector}" /> 

DataContext этого элемента (т.е. связывание мишени) является UserControl себя. MStatusDisplaySelector является сложным селектором и выбирает DataTemplate на основе нескольких свойств этого UserControl (которые все просты DependencyProperty).

Проблема в том, что при изменении любого из этих свойств может потребоваться выбор другого шаблона, и я хочу обновить ContentPresenter. Это, очевидно, не происходит. Каков наилучший способ обойти это?

В идеале я бы хотел избежать реализации обратных вызовов изменений во всех задействованных свойствах. Мало того, что это слишком многословно, но в селекторе шаблонов может понадобиться использовать другой набор свойств позже, и поддерживать это в синхронизации не удобно. Тем не менее, вероятно, ОК обновить шаблон на любые изменение свойства.

P.S. Предположим, что логика MStatusDisplaySelector слишком сложна, чтобы свести ее к традиционному селектору стиля с помощью Style.Triggers. Я бы хотел, чтобы он оставался в коде.

+0

Звучит как триггер стиля с сеттерами, которые меняют шаблон, или же селектор шаблонов. Кажется немного необычным изменение всего шаблона при изменении свойств (обычно вы показываете или скрываете элементы шаблона на основе свойств и изменяете шаблоны только при изменении типа среды выполнения ContentControl.DataContext), но без каких-либо подробностей я действительно не могу судить. –

+0

Ну, @Ed, я понимаю, что это может быть не совсем WPF-подобное (я только изучаю), но, как я уже сказал, 'MStatusDisplaySelector' не является тривиальным, и я не вижу, как я мог бы реализовать его в xaml (или скорее, это будет чрезвычайно многословно). Например, одним из свойств является сложный побитовый шаблон, на основе которого мне может понадобиться отображать изображение или сетку изображений или текст или вообще скрыть его. Написание такой вещи в кодировке - это легко, но не так в xaml. – Zeus

+0

Вы можете сделать эту логику в конвертере значений, я думаю. Конечно, вы бы не пытались написать эту логику в XAML. В любом случае это звучит так, как вы это продумали. –

ответ

1

Добавить это в код UserControl:

protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e) 
    { 
     if (e.OldValue != null && e.NewValue != null && e.Property.ToString() == "Title") 
     { 
      System.Diagnostics.Debug.WriteLine(e.Property.ToString() + " > " + e.OldValue.ToString() + " : " + e.NewValue.ToString()); 
      /* You can call your TemplateSelector method here, or put some code here */ 
     } 
     base.OnPropertyChanged(e); 
    } 

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

+0

Таким образом, я могу обнаружить изменение. Это самый простой способ. Но главный вопрос: какое действие я должен предпринять? Как я могу подтолкнуть мой ContentPresenter к обновлению своего шаблона? Я мог бы, вероятно, удалить декларацию 'ContentTemplateSelector' и назначить' ContentTemplate' из кода этого обработчика ... Но это выглядит еще более не WPF для меня ... – Zeus

+0

@ Zeus Непонятно, как обновить шаблон. Всякий раз, когда свойство, связанное с 'Content', изменяет' Binding', будет обновлено 'Content', которое в свою очередь вызовет' TemplateSelector'. Таким образом, вы можете изменить 'ViewModel: bound-property' в методе' OnPropertyChanged', который, в свою очередь, обновит 'Content'. – AnjumSKhan

+0

Но цель привязки - это 'UserControl'. Другими словами, эффективно '.Content = this' (я не назначал« Имя »в моем исходном коде выше). Если я заставляю это назначение в «OnPropertyChanged», он ничего не сделает, потому что сам объект не изменился. Только некоторые из его свойств. – Zeus

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