I have a MVVM view and viewmodel. In the constructor of my viewmodel I pass a list of IObservable messages and subscribe to them through a simple class sitting outide of my viewmodel and view
Outside class
{
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 };
}
}
In the view model constructor
subscription = receiveMessages.Subscribe(MessageReceived);
private void MessageReceived(GvsMessage message)
{
MyProperty = true;
}
On receiving a message I want to create my view not before that. Although the viewmodel is created before to handle property change etc
The problem is that I get "the calling thread must be sta because many ui components require this". Could someone please help
As we spoke in the comments you need to use a Dispatcher
which can be acquired from different parts of the app.
To initialize the dispatcher you can use this snippet:
protected static Dispatcher _d;
if (Application.Current != null)
{
_d = Application.Current.Dispatcher;
}
else
{
_d = Dispatcher.CurrentDispatcher;
}
Explanation:
The first dispatcher is done when the application has UnitTests
when you run the tests this dispatcher will not be null,
The second one is the current Dispatcher
used by your application.
After you have this in your code when initializing your VM
now you can send messages Actions
, Events
to the UI Thread.
I have a little method just for that:
public static void UIThread(Action action)
{
if (_d == null)
{
if (Application.Current != null)
{
_d = Application.Current.Dispatcher;
}
else
{
_d = Dispatcher.CurrentDispatcher;
}
}
_d.Invoke(action);
}
This function will accept lambda, like so:
UIThread(() =>
{
Processing = true;
Message = "Working ...";
//in your case you would raise the Loaded event here
});
This way you EventHandler
in your view will have no problem showing that view.
If you need any more info let us know.
HTH
I resolved this by creating the view and the viewmodel in the constructor. In the propertychanged event I just set a property IsVisible to 'true' binds the window visibility
<Window.Visibility>
<Binding Path="IsVisible" Converter="{StaticResource BoolToVisibilityConverter}" Mode="TwoWay"/>
</Window.Visibility>