Работая с шаблоном MVVM, у меня есть пара классов моделей представлений, которые представляют двухуровневую иерархию данных, каждый с соответствующим UserControl
, который представляет ее представление.Оба класса модели представления реализуют INotifyPropertyChanged
, а модель представления корневого уровня предоставляет свойство, которое относится как к его собственному представлению, так и к дочернему представлению.
Представление корневого уровня получает модель представления корневого уровня в качестве контекста данных.и явно назначает контекст данных для его содержимого.Однако также необходимо привязать одно из свойств дочернего представления к вышеупомянутому общему свойству.Вот как я пытался добиться этого, но он не работает:
<UserControl x:Name="rootView">
<StackPanel>
<!-- other controls here -->
<my:ChildView
DataContext="{Binding Path=SelectedChild}"
EditingMode="{Binding ElementName=rootView, Path=DataContext.EditingMode />
</StackPanel>
</UserControl>
Хотя ошибок привязки во время выполнения нет, и дочернее представление правильно связывается с соответствующим экземпляром модели дочернего представления, его свойством EditingMode
никогда не устанавливается.Я запустил тесты, чтобы убедиться, что соответствующее свойство модели представления изменяется и уведомляет об этом с помощью INotifyPropertyChanged
, но привязка не может его обнаружить.
Есть ли лучший способ объявить эту привязкуили я сделал более простую архитектурную ошибку?
Большое спасибо за ваш совет,
Тим
Обновление: По запросу я публикую некоторыекод, показывающий очень упрощенную версию моих представлений и моделей представлений, а также результаты проведенного мной эксперимента, который может дать некоторые дополнительные подсказки.
// The relevant parts of the ParentViewModel class
public class ParentViewModel : INotifyPropertyChanged
{
// Although not shown, the following properties
// correctly participate in INotifyPropertyChanged
public ChildViewModel SelectedChild { get; private set; }
public ContentEditingMode EditingMode { get; private set; }
}
// The relevant parts of the ChildViewModel class
public class ChildViewModel : INotifyPropertyChanged
{
// No properties of ChildViewModel affect this issue.
}
// The relevant parts of the ParentView class
public partial class ParentView : UserControl
{
// No properties of ParentView affect this issue.
}
// The relevant members of the ChildView class
public partial class ChildView : UserControl
{
public static readonly DependencyProperty EditingModeProperty =
DependencyProperty.Register(
"EditingMode",
typeof(ContentEditingMode),
typeof(PostView)
);
public ContentEditingMode EditingMode
{
get { return (ContentEditingMode)GetValue(EditingModeProperty); }
set { SetValue(EditingModeProperty, value); }
}
}
// The enumeration used for the EditingMode property
public enum ContentEditingMode
{
Html,
WYSYWIG
}
Мое намерение состоит в том, чтобы DataContext
экземпляру родительского представления будет назначен экземпляр ParentViewModel
, и он, в свою очередь, назначит значение своего свойства SelectedChild
для DataContext
вложенного ChildView
.Кажется, что все это работает правильно, но проблема возникает из-за того, что связь между ParentViewModel.EditingMode
и ChildView.EditingMode
не работает.
В попытке проверить, есть ли проблема с моим выражением привязки, я представилTextBlock
, смежный с ChildView
и связанный с ним так же, как свойство ParentViewModel.EditingMode
:
<UserControl x:Name="rootView">
<StackPanel>
<!-- other controls here -->
<TextBlock Text="{Binding ElementName=rootView, Path=DataContext.EditingMode}" />
<my:ChildView
DataContext="{Binding Path=SelectedChild}"
EditingMode="{Binding ElementName=rootView, Path=DataContext.EditingMode />
</StackPanel>
</UserControl>
В этом тесте TextBlock
корректно обновляется каждый раз, когда изменяется свойство источника.Однако, если я установлю точку останова на установщик ChildView.EditingMode
, он никогда не получит удар.
Я сбит с толку!