MVVM Light и несколько экземпляров одного и того же ViewModel, без обновления пользовательского интерфейса

1

Некоторое время я использовал MVVM Light, поэтому у меня есть небольшой опыт, однако я никогда не пробовал делать несколько экземпляров одной и той же viewmodel

В принципе, я создал viewmodel usercontrol которого есть viewmodel и я использую 4 экземпляра этого элемента управления в окне WPF.

Вот как я делаю привязку в xaml, довольно простой материал.

<UserControl.DataContext>
   <Binding Path="PodView" Source="{StaticResource Locator}"/>
</UserControl.DataContext>

<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="6,0,0,0" Text="{Binding PodModel}"/>

Вот код локатора службы.

public class ViewModelLocator
{
    /// <summary>
    /// Initializes a new instance of the ViewModelLocator class.
    /// </summary>
    public ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        SimpleIoc.Default.Register<MainViewModel>();
        SimpleIoc.Default.Register<PODViewModel>();
    }

    public MainViewModel Main
    {
        get
        {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }

    public PODViewModel PodView
    {
        get
        {
            //return ServiceLocator.Current.GetInstance<PODViewModel>(Guid.NewGuid().ToString());
            return new PODViewModel();
        }
    }

    public static void Cleanup()
    {
        // TODO Clear the ViewModels
    }
}

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

Хорошо, так что теперь на вопрос. В viewmodel меня есть свойство, подобное этому, которое связано с viewmodel

private string _PodModel;
public string PodModel
{
    get { return _PodModel; }
    set
    {
        if (_PodModel != value)
        {
            _PodModel = value;
             RaisePropertyChanged(() => PodModel);
        }
    }
}

Теперь в конструкторе у меня есть это, что отлично работает, и я проверяю это как в blend, так и при запуске программы.

public PODViewModel()
{
    if (IsInDesignMode)
    {
        ////    // Code runs in Blend --> create design time data.                
        PodModel = "HSA3";    // <-- This works fine
    }
    else
    {
        ////    // Code runs "for real"                
        PodModel = "Fred";    // <-- This works fine
    }
}

Теперь проблема в том, что каждый элемент управления имеет поток для выполнения длинной задачи и изменяет свойство PodModel. При этом я не получаю никаких исключений, но пользовательский интерфейс не обновляется.

PodModel = "blah blah blah";

Поэтому я переместил код в поток пользовательского интерфейса так, но пользовательский интерфейс все равно не будет обновляться.

DispatcherHelper.CheckBeginInvokeOnUI(() =>
   {
       PodModel = "blah blah blah";
   });

Я поставил точку останова на свойство set, и я вижу, что свойство действительно меняется.

Любые идеи, почему пользовательский интерфейс не будет обновляться?

Обновление 1: я заметил, что есть 2 вызова для получения экземпляра PodViewModel

  • 0
    уточнить: 1) есть ли 2 вызова PodViewModel для PodViewControl? это подозрительно Убедитесь, что вы не установили DataContext в коде позади. 2) у каждого PodViewModel есть поток, обновляющий ViewModel? если нет, то где начинается поток?
  • 0
    1) насколько я вижу, нет. У меня только один раз в xaml установлена привязка, и я не устанавливаю текст данных в коде позади. 2) Да, это так. Существует поток, созданный при загрузке UserControl. Этот поток запускается все время, пока выполняется приложение, и изменяет свойства в ViewModel.
Показать ещё 2 комментария
Теги:
wpf
mvvm-light

1 ответ

2

Я думаю, что проблема в том, что свойство PodView всегда возвращает новый объект. Это приводит к ситуации, когда обновляется другой экземпляр модели представления (например, устанавливая свойство PodModel в "бла-бла-бла"), чем привязан к пользовательскому интерфейсу. Он не может работать, потому что пользовательский интерфейс не знает, что его экземпляр модели просмотра был обновлен. Чтобы подтвердить это, попробуйте использовать следующий код:

private PODViewModel  _podView = new PODViewModel();  
public PODViewModel PodView
{
    get
    {
        return _podView ;
    }
}
  • 0
    Я попробовал ваш код и могу подтвердить, что вы правы. Есть ли способ заставить это работать?
  • 0
    Вы должны хранить ссылку на модель представления в переменной / поле и не извлекать ее из ViewModelLocator каждый раз, когда вам это нужно. Я не могу сказать больше, потому что я не вижу код элемента управления / потока, ответственного за обновление свойства PodModel.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню