2016-05-26 2 views
1

У меня есть вид MVVM и модель просмотра. В конструкторе моего ViewModel я прохожу список сообщений IObservable и подписаться на них через простой класс сидит outide моей ViewModel и видаСоздание представления при получении сообщения

Вне классе

{ 
    viewModel = 
      new ViewModelClass(
       responseHandler.AsObservable()); 

    viewModel.PropertyChanged += ViewModel_PropertyChanged; 
} 

private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 

    if (e.PropertyName == nameof(ViewModelClass.MyProperty)) 
    { 
     // Error here 
     view = new MyViewClass() { DataContext = viewModel }; 

    } 
} 

В виде модель конструктора

 subscription = receiveMessages.Subscribe(MessageReceived); 

     private void MessageReceived(GvsMessage message) 
     { 
      MyProperty = true; 

     } 

При получении сообщения я хочу создать свое мнение не раньше этого. Хотя viewmodel создается прежде, чем обрабатывать изменение свойств и т. Д.

Проблема в том, что я получаю «вызывающий поток должен быть sta, потому что многие компоненты ui требуют этого». Может ли кто-нибудь помочь?

+0

Нам нужно больше информации, так как здесь есть MT (многопоточность). Нам не нужен подробный пример, который мы могли бы понять, как ваше приложение построено. – XAMlMAX

+0

Внешний класс сидит в потоке, и именно по этой причине я не могу изменить представление (создать представление и т. Д.) В ViewModel_PropertyChanged. Я попробовал взломать таймер, чтобы проверить, изменилась ли моя собственность и она работает. Но что это за хороший способ сделать это? Создание события также дает ту же проблему – user2837961

+0

ОК, ваш 'View' должен быть создан в разделе «Основной пользовательский интерфейс». Вся обработка данных может быть выполнена в «Background Thread», иначе '' WPF' не понравится, потому что, если вы создаете 'UserControl' в потоке, отличном от UI, этот поток является владельцем созданного им объекта. – XAMlMAX

ответ

0

Как мы говорили в комментариях, вам нужно использовать Dispatcher, который можно приобрести в разных частях приложения.
Для инициализации диспетчера вы можете использовать этот фрагмент кода:

protected static Dispatcher _d; 
if (Application.Current != null) 
{ 
    _d = Application.Current.Dispatcher; 
} 
else 
{ 
    _d = Dispatcher.CurrentDispatcher; 
} 

Пояснение:
Первый диспетчеру делается, когда приложение имеет UnitTests при выполнении тестов этот диспетчер не будет аннулирована,
второй - текущий Dispatcher, используемый вашим приложением.
После этого в вашем коде при инициализации VM теперь вы можете отправлять сообщения Actions, Events в пользовательский интерфейс.
У меня есть маленький метод только для этого:

public static void UIThread(Action action) 
    { 
     if (_d == null) 
     { 
      if (Application.Current != null) 
      { 
       _d = Application.Current.Dispatcher; 
      } 
      else 
      { 
       _d = Dispatcher.CurrentDispatcher; 
      } 
     } 
     _d.Invoke(action); 
    } 

Эта функция принимает лямбда, например, так:

UIThread(() => 
     { 
      Processing = true; 
      Message = "Working ..."; 
      //in your case you would raise the Loaded event here 
     }); 

Таким образом, вы EventHandler на ваш взгляд, не будет иметь никаких проблем с указанием этой точки зрения.
Если вам нужна дополнительная информация, сообщите нам.
HTH

0

Я решил это, создав представление и viewmodel в конструкторе. В событии propertychanged я просто установил свойство IsVisible на «true» связывает видимость окна

<Window.Visibility> 
    <Binding Path="IsVisible" Converter="{StaticResource BoolToVisibilityConverter}" Mode="TwoWay"/> 
</Window.Visibility> 
Смежные вопросы