WPF: настройка DataContext для UserControl с не работающей привязкой в ​​XAML - PullRequest
5 голосов
/ 18 апреля 2010

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

Настройка заключается в том, что у меня есть view & viewModel, в которой хранятся данные пользователя (родитель), и, чтобы попытаться упростить задачу, я поместил раздел этого представления в отдельный view & viewModel (дочерний элемент). Дочернее представление определяется как 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 со свойством int просто для его проверки:

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

И это прекрасно работает.

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

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

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

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

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

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

Ответы [ 3 ]

2 голосов
/ 10 августа 2010

Я искал то же самое и нашел один способ сделать это. По сути, я связал DataContext дочернего элемента с DataContext некоторого родителя (окна), используя

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

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

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

Мне кажется, что это хак, но лучше, чем привязка к модели представления верхнего уровня.

2 голосов
/ 26 ноября 2011

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

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

parentView.ChildView.DataContext = parentViewModel.childViewModel;
Подход

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

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

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

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

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

2 голосов
/ 19 апреля 2010

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

Попробуйте вызвать событие PropertyChanged в свойстве childViewModel.

Ура, Laurent

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...