2010-04-18 3 views
5

Я пытаюсь запустить свое первое приложение WPF, используя MVVM, и я столкнулся с небольшой проблемой привязки.WPF: настройка DataContext UserControl с привязкой, не работающей в XAML

Установки является то, что у меня есть вид & ViewModel который содержит информацию о пользователях (родитель), и попытаться держать вещи простыми, я положил часть этой точки зрения в отдельное окно & ViewModel (ребенок). Вид child определяется как UserControl.

Проблема, с которой я столкнулась, заключается в том, как установить DataContext дочернего представления (UserControl). Мой родитель ViewModel имеет свойство, которое обнажает ребенок ViewModel, как так:

class ParentViewModel: INotifyPropertyChanged 
{ 
    public ChildViewModel childViewModel { get; set; } 
    //... 
} 

В XAML для моего родительского вида (который имеет это DataContext набор к ParentViewModel), я пытаюсь установить DataContext в целях ребенка следующим образом:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Однако это не работает. DataContext дочернего представления установлен в тот же DataContext, что и родительский вид (т. Е. ParentViewModel), как будто я вообще не устанавливал его. Я также попытался установить DataContext в ребенке видеть себя, который также не работает:

<UserControl x:Class="DietRecorder.Client.View.ChildView" 
    DataContext="childViewModel" 

Я нашел несколько способов обойти это. По мнению ребенка, я могу связать все, включив ChildViewModel в пути:

<SomeControl Visibility="{Binding Path=childViewModel.IsVisible}"> 

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

parentView.Show(); 
parentView.ChildView.DataContext = parentViewModel.childViewModel; 

Этот код также заставляет меня чувствовать себя неловко, то, с нарушением LOD и всеми.

Это просто DataContext, что, как представляется, проблема - я могу связать другие вещи ребенка, например, я пытался связывать FontSize к ИНТ собственности просто проверить:

<views:ChildView 
    x:Name="ChildView" 
    FontSize="{Binding Path=someVal}"/> 

И это работает хорошо.

Но я уверен, что привязка DataContext должна работать - я видел похожие примеры такого рода вещей. Я пропустил что-то очевидное здесь? Есть ли причина, по которой это не сработает? Есть где-то орфографическая ошибка? (Я переименовал вещи в вашу пользу, поэтому вы не сможете мне помочь там в любом случае).

Любые мысли приветствуются.

Редактировать

Рассматривая этот код еще раз, мне кажется, я сделал ошибку где-то, как показано в следующем XAML в родительское представление делает сейчас появляется на работе:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Я не знаю, почему я не мог заставить его работать изначально или что я мог бы изменить, чтобы он работал. Возможно, это была проблема с INotifyPropertyChanged, как и один из ответов. Ну ладно, вперед и вверх ..

ответ

2

Я подозреваю, что это связано с тем, что свойство childViewModel не вызывает событие PropertyChanged. Когда оценивается привязка, возможно, что это свойство равно null (в этом случае DataContext просто вернется к родительскому). Когда childViewModel создается позже, событие PropertyChanged не создается, и привязка никогда не сообщается о том, что теперь есть DataContext.

Попробуйте поднять событие PropertyChanged в свойстве childViewModel.

Cheers, Laurent

+0

Хорошее мышление, но никакой радости я боюсь. Я думал, что это может быть связано с порядком, но child viewModel должен быть доступен, когда происходит привязка - и он работает, когда я устанавливаю размер шрифта с использованием свойства int, которое происходит одновременно, и это не делает, t используйте PropertyChanged. –

2

Я искал то же самое, и я нашел один способ сделать это. В принципе, я связала DataContext ребенка к DataContext некоторых родительским (окна) с помощью

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

где я настроил x:Name="_topLevel" на каком-то родительский элементе управления (окно).

Я попытался использовать RelativeSource/FindAncestor вместо ElementName, но это не сработало - но это была, вероятно, моя ошибка.

Чувства, как рубить меня, но лучше привязки к модели верхнего уровня.

+0

Хотя я еще не пробовал, это должно сработать, поэтому я дам вам +1 за усилия после всего этого времени, но это решение имеет ту же проблему, что и одно из решений, которые я предложил выше, а именно, что ребенок знает о родителе. Это либо плохой запах, либо реальная проблема, в зависимости от того, используете ли вы ребенка в разных родительских представлениях или нет. При проверке кода для этого ответа я обнаружил, что теперь он работает, хотя я не уверен, почему - см. Редактирование для деталей. –

2

Это не ответ на вопрос, но может помочь другим в тех же обстоятельствах.

я попал именно эту проблему и обнаружили, что

parentView.ChildView.DataContext = parentViewModel.childViewModel; 

подход работал (хотя я обнаружил, что он работал, прежде чем делать Show()), но имел те же постеснялся об этом как оригинал спрашивающий так попробовал

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

подход, который также, казалось, сработал. Но потом я снова попытался вернуться к исходному коду и оригинальному XAML, и теперь он внезапно также работал. Это отражает поведение первоначального опросчика, когда автор думал, что они совершили ошибку где-то, поскольку XAML, казалось, начал работать без какой-либо очевидной причины.

Единственное изменение, которое я вижу, - это то, что Visual Studio теперь показывает образцы данных в UserControl во время разработки, поэтому где-то он кэшировал некоторые примеры данных, и это, похоже, заставляет его работать. Я не уверен, какие из двух изменений сделали это, к сожалению.

Внешний вид образцов данных заставляет меня задаться вопросом, связана ли проблема с использованием d: DataContext, который у меня есть в родительском и дочернем XAML-файлах, но это всего лишь предположение.

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