简体   繁体   中英

WPF, C#, MVVM Notify ViewModel dynamically in changes from static vars in Model

I have ViewModel that makes some functions. Funcs are initiate by button, i have command on button click.

ViewModel.cs

class WindowViewModel : INotifyPropertyChanged
{
    public WindowViewModel()
    {
        canExecute = true;
    }

    public ICommand ApplyKMMCommand //command for button click, works great, tested
    {
        get
        {
            return applyKMMCommand ?? (applyKMMCommand = new Commands.CommandHandler(() => 
                                                       ApplyKMMToNewImage(), canExecute));
        }
    }

    private bool canExecute;
    private ICommand applyKMMCommand;

    public void ApplyKMMToNewImage()
    {
        ApplyKMM.Init(); //algorithm name
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public BitmapImage DisplayedImage //displaying image that i work with
    {
        get { return Bitmaps.Filepath; }
        set { Bitmaps.Filepath = value; NotifyPropertyChanged(nameof(DisplayedImage)); }
    }
}

Now, my ApplyKMM.Init()

class ApplyKMM
{

    public static void Init()
    {
        Bitmaps.Filepath = //do some thing with it...
    }
}

And my Models.Bitmaps.cs

    static public BitmapImage Filepath
    {
        get { return filepath; }
        set { filepath = value; }
    }

    static private BitmapImage filepath{ get; set; }

The problem is, when i make ApplyKMM.Init the Image control that is binded to View not change their value.

Without ApplyKMM i can do in ViewModel that thing:

DisplayedImage = //do things with bitmap...

And then, Image that is presented in View change (after making things with that image).

Can you tell me, how to notify ViewModel, that somewhere in code filepath from Models changed?

EDIT:

Binding in View Looks like standard binding:

<Image Source="{Binding DisplayedImage}"/>

Button click works too, i have problem only with communication between Models->ApplyKMM->ViewModel

EDIT2:

Properties Filepath is storage in Models folder, not folder where function ApplyKMM is. Look into my edit, i try to make something like:

Models -> ApplyKMM -> ViewModel . From Models, i get Filepath . Then, i using function ApplyKMM that is in another namespace. Then, after working on bitmap with ApplyKMM func i want to somehow notify ViewModel , that work on Model is done (for example, convert to grayscale) and i want to show that grayscale image in VM. It works, when i want to do Model -> ViewModel ( ApplyKMM is in VM class) but i want to move out ApplyKMM away from ViewModel . And that when staris starts for me.

Basically it is not a good practice to notify changes of a static variable to an instance.

Then, let's look at your code:

Bitmaps class does not implement INotifyPropertyChanged , so when Filepath changes, nothing will be notified (of course, it is a static property)

In your case, you should use local variable to hold DisplayedImages . Then changes on DisplayedImage should be updated by the binding.

BitmapImage _displayedImage;
public BitmapImage DisplayedImage 
{
    get { return displayedImage; }
    set { displayedImage = value; NotifyPropertyChanged(nameof(DisplayedImage)); }
}

It appears like you want to notify when a static property changes. For this, you may use the StaticPropertyChanged event.

class ApplyKMM
{
    #region Properties
    static BitmapImage _Filepath;
    public static BitmapImage Filepath
    {
        get { return _Filepath; }
        set { if (_Filepath != value) { _Filepath = value; NotifyPropertyChanged(nameof(Filepath)); } }
    }
    #endregion

    #region Static NotifyPropertyChanged
    public static void NotifyStaticPropertyChanged(string propertyName)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
    }

    public void NotifyAllStaticPropertyChanged()
    {
        NotifyStaticPropertyChanged(string.Empty);
    }

    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
    #endregion
}

Please take note that this is available from WPF Version 4.5.
You might also find this question interesting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM