OnPropertyChanged和实例属性 [英] OnPropertyChanged and instance property
问题描述
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屋!