OnPropertyChanged和实例属性 [英] OnPropertyChanged and instance property

查看:461
本文介绍了OnPropertyChanged和实例属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为Layer_Properties的WPF窗口,一个名为MainWindow的WPF窗口和一个MapViewModel. 在MapViewModel中,我创建了一个对象< Layer_Properties>.我想观察称为Stops_List的Layer_Properties属性的任何更改,以便在MainWindow.xaml中刷新树视图

Layer_Properties类

public partial class Layer_Properties : Window, INotifyPropertyChanged
{
    //Properties
    
    public MainWindow mw = (MainWindow)Application.Current.MainWindow;


    private ObservableCollection<Stop> _Stops_List = new ObservableCollection<Stop>();

    public ObservableCollection<Stop> Stops_List   // property
    {
        get { return _Stops_List; }   // get method
        set { _Stops_List = value; }  // set method
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

MapViewModel类

public class MapViewModel : INotifyPropertyChanged
{
    public MapViewModel()
    {
        _activeLayerProperties = new Layer_Properties();
        _numberOfStops= _activeLayerProperties.Stops_List.Count;
    }

    private Map _map;
    public MapView _mapView;
    public MainWindow mw = (MainWindow)Application.Current.MainWindow;

    private ObservableCollection<Layer_Properties> layersPool = new ObservableCollection<Layer_Properties>();
    public ObservableCollection<Layer_Properties> LayersPool
    {
        get { return layersPool; }
        set
        {
            layersPool = value;
            OnPropertyChanged(nameof(LayersPool));
        }
    }

    private Layer_Properties _activeLayerProperties;
    public Layer_Properties activeLayerProperties
    {
        get { return _activeLayerProperties; }
        set
        {
            _activeLayerProperties = value;
            OnPropertyChanged(nameof(activeLayerProperties.Stops_List));
        }
    }

    private int _numberOfStops;
    public int numberOfStops
    {
        get { return _numberOfStops; }
        set
        {
            _numberOfStops = value;
            if(_numberOfStops >0)
            {
               //Refresh treeview
            } 
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Raises the <see cref="MapViewModel.PropertyChanged" /> event
    /// </summary>
    /// <param name="propertyName">The name of the property that has changed</param>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var propertyChangedHandler = PropertyChanged;
        if (propertyChangedHandler != null)
            propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
    }
}

逻辑如下: 将所有Layer_Properties实例添加到ObservableCollection< Layer_Properties>中. LayersPool.

将layer_Properties实例复制到_mapViewModel.activeLayerProperties以便知道什么是活动实例.

每次Stops_List.Count更改时刷新树视图.任何帮助将不胜感激.

解决方案

使用相同的INPC实现. 否则,请仅使自己和查看您代码的人感到困惑. 例如,您可以调用这样的基本实现,并从中继承您的类. 示例:

/// <summary>Base class implementing INotifyPropertyChanged.</summary>
public abstract class BaseINPC : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>Called AFTER the property value changes.</summary>
    /// <param name="propertyName">The name of the property.
    /// In the property setter, the parameter is not specified. </param>
    public void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

ObservableCollection类型的集合属性,我建议仅进行读取. 也就是说,他们只应有一个二传手. 这将有助于避免许多随机的错误和错误.

public class MapViewModel : BaseINPC
{
    public ObservableCollection<Layer_Properties> LayersPool { get; }
        = new ObservableCollection<Layer_Properties>();

    private Layer_Properties _activeLayerProperties;
    public Layer_Properties activeLayerProperties
    {
        get => _activeLayerProperties; 
        set
        {
            _activeLayerProperties = value;
            RaisePropertyChanged();
        }
    }

在ViewModel中,不允许引用UI元素及其创建. 更不用说您的VM收到对Window的引用这一事实. VM甚至不需要知道哪种视图类型:WPF,窗体或控制台. 您的架构解决方案非常糟糕.

更详细地描述数据的结构和所需的表示形式.

i have a WPF window called Layer_Properties, a WPF window called MainWindow and a MapViewModel. in the MapViewModel i create an object<Layer_Properties> and i want to observe any changes of a Layer_Properties property called Stops_List in order to refresh a treeview in MainWindow.xaml

class Layer_Properties

public partial class Layer_Properties : Window, INotifyPropertyChanged
{
    //Properties
    
    public MainWindow mw = (MainWindow)Application.Current.MainWindow;


    private ObservableCollection<Stop> _Stops_List = new ObservableCollection<Stop>();

    public ObservableCollection<Stop> Stops_List   // property
    {
        get { return _Stops_List; }   // get method
        set { _Stops_List = value; }  // set method
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

class MapViewModel

public class MapViewModel : INotifyPropertyChanged
{
    public MapViewModel()
    {
        _activeLayerProperties = new Layer_Properties();
        _numberOfStops= _activeLayerProperties.Stops_List.Count;
    }

    private Map _map;
    public MapView _mapView;
    public MainWindow mw = (MainWindow)Application.Current.MainWindow;

    private ObservableCollection<Layer_Properties> layersPool = new ObservableCollection<Layer_Properties>();
    public ObservableCollection<Layer_Properties> LayersPool
    {
        get { return layersPool; }
        set
        {
            layersPool = value;
            OnPropertyChanged(nameof(LayersPool));
        }
    }

    private Layer_Properties _activeLayerProperties;
    public Layer_Properties activeLayerProperties
    {
        get { return _activeLayerProperties; }
        set
        {
            _activeLayerProperties = value;
            OnPropertyChanged(nameof(activeLayerProperties.Stops_List));
        }
    }

    private int _numberOfStops;
    public int numberOfStops
    {
        get { return _numberOfStops; }
        set
        {
            _numberOfStops = value;
            if(_numberOfStops >0)
            {
               //Refresh treeview
            } 
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// Raises the <see cref="MapViewModel.PropertyChanged" /> event
    /// </summary>
    /// <param name="propertyName">The name of the property that has changed</param>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var propertyChangedHandler = PropertyChanged;
        if (propertyChangedHandler != null)
            propertyChangedHandler(this, new PropertyChangedEventArgs(propertyName));
    }
}

The logic is as follows; add all Layer_Properties instances to an ObservableCollection<Layer_Properties> LayersPool.

Copy layer_Properties instance to a _mapViewModel.activeLayerProperties in order to know what is the active instance.

Refresh the treeview everytime Stops_List.Count changes. Any help will be appreciated.

解决方案

Use the same implementation of INPC. Otherwise, only confuse yourself and those who look at your code. For example, you can call such a basic implementation and inherit your classes from it. Example:

/// <summary>Base class implementing INotifyPropertyChanged.</summary>
public abstract class BaseINPC : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>Called AFTER the property value changes.</summary>
    /// <param name="propertyName">The name of the property.
    /// In the property setter, the parameter is not specified. </param>
    public void RaisePropertyChanged([CallerMemberName]string propertyName = "")
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

Collection properties of type ObservableCollection I recommend doing ONLY FOR READING. That is, they should only have a setter. This will help to avoid many random errors and bugs.

public class MapViewModel : BaseINPC
{
    public ObservableCollection<Layer_Properties> LayersPool { get; }
        = new ObservableCollection<Layer_Properties>();

    private Layer_Properties _activeLayerProperties;
    public Layer_Properties activeLayerProperties
    {
        get => _activeLayerProperties; 
        set
        {
            _activeLayerProperties = value;
            RaisePropertyChanged();
        }
    }

In ViewModel, no references to UI-elements, their creation, are allowed. Not to mention the fact that your VM receives a reference to the Window. VM does not even need to know what type of View: WPF, Forms or Console. You have a very broken architecture Solutions.

Describe in more detail the structure of your Data and the Presentation required for it.

这篇关于OnPropertyChanged和实例属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆