srinivas
srinivas

Reputation: 89

accessing dependency property between viewmodels

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

Answers (2)

Mustafa Mutasim
Mustafa Mutasim

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 of B would know the associated instance of A and directly register a handler for A's PropertyChanged event


Changes:

  • Create SharedClass For Test Only (its content should be moved to class A or kept in the case of A is Singleton)
  • SharedClass.UpdatePropertyA(new SharedClass.PropertyA_EventArgs()...
  • SharedClass.PropertyAChanged += SharedClass_PropertyAChanged;
  • private void SharedClass_PropertyAChanged(object? sender, SharedClass.PropertyA_EventArgs e)

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

tovergieter
tovergieter

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

Related Questions