Reputation: 89
I have 2 viewmodels say,
viewmodel is bound to view
class A : INotifyPropertyChanged
{
public A(){}
private bool _propertya;
public bool PropertyA
{
get{return _propertya;}
set{_propertya=value; onPropertyChanged("PropertyA");}
}
private void onPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
And another viewmodel where my properties are linked to another view
class B : INotifyPropertyChanged
{
public B(){}
private bool _propertyb;
public bool PropertyB
{
get{ return _propertyb;}
set{_propertyb=value; onPropertyChanged("PropertyB");}
}
private void onPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
When PropertyB is changed , I want to check the value of PropertyA from another viewmodel and return bool value based on condition. How can i get the instance of PropertyA from another viewmodel in class B
Upvotes: -2
Views: 104
Reputation: 588
General Solution (Using EventArgs
)
*** Important note from @Clemens ***
Using
static classes
in view models is generally a bad idea. It would be far simpler when an instance ofB
would know the associated instance ofA
and directly register a handler forA
'sPropertyChanged
event
Changes:
A
or kept in the case of A
is Singleton
)public static class SharedClass
{
public class PropertyA_EventArgs : EventArgs
{
public bool PropertyA_OldValue { get; set; }
public bool PropertyA_NewValue { get; set; }
}
public static event EventHandler<PropertyA_EventArgs> PropertyAChanged;
public static void UpdatePropertyA(PropertyA_EventArgs PropertyA_Event)
{
PropertyAChanged?.Invoke(null, PropertyA_Event);
}
}
public class A : INotifyPropertyChanged
{
public A() { }
private bool _propertya;
public bool PropertyA
{
get { return _propertya; }
set
{
// ----------------------------------
SharedClass.UpdatePropertyA(
new SharedClass.PropertyA_EventArgs()
{
PropertyA_OldValue = _propertya,
PropertyA_NewValue = value
});
// ----------------------------------
_propertya = value; onPropertyChanged("PropertyA");
}
}
private void onPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public class B : INotifyPropertyChanged
{
public B()
{
// ----------------------------------
SharedClass.PropertyAChanged += SharedClass_PropertyAChanged;
// ----------------------------------
}
// ----------------------------------
private void SharedClass_PropertyAChanged(object? sender, SharedClass.PropertyA_EventArgs e)
{
//Usage :
// To Access Old Value: e.PropertyA_OldValue
// To Access New Value: e.PropertyA_NewValue
//...
}
// ----------------------------------
private bool _propertyb;
public bool PropertyB
{
get { return _propertyb; }
set { _propertyb = value; onPropertyChanged("PropertyB"); }
}
private void onPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Upvotes: -1
Reputation: 19
It seems like you are searching for a solution to have some sort of global/shared state. This state can than be used by different classes like the view models. I don't know how you've designed parts like navigation but I would suggest to use dependency injection and a singleton for this.
If you are not familiar with dependency injection, in essence it makes it possible to inject a class and their responsibilities into another class. For example I got a class with a global state called DataContext
, I want to use this class across multiple view models or models. I can inject the DataContext
into said view models by using the constructor. For example:
public class DataContext {}
public class ViewModel {
private readonly DataContext _context;
public ViewModel(DataContext context) {
_context = context;
}
}
The DataContext
will be a singleton, meaning for dependency injection only one instance will be used. To use dependency injection in your WPF application, packages such as Microsoft.Extensions.DependencyInjection
can be used. In the App.xaml.cs
, initialization of dependency injection can be done by using the Startup
event of the application. For example:
private void Application_Startup(object sender, StartupEventArgs e) {
var serviceCollection = new ServiceCollection();
serviceCollection.AddTransient<MainWindow>();
serviceCollection.AddSingleton<DataContext>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var mainWindow = serviceProvider.GetService<MainWindow>();
mainWindow.Show();
}
Adding the MainWindow
as a transient is needed to make the dependency injection work (I believe, but I'm not 100% sure of that). More information about dependency injection and WPF can be found here. This might seem overwhelming but I think this is a very good approach to solve your issue. Hope it helps :)
Upvotes: -1