Notify Property Changed Event without setter - c#

I am developing a WPF application using MVVM architect, and as a common scenario using properites to Notify Changes like
public List<EmployeeInfo> Employees
{
get
{
return _employees;
}
set
{
_employees = value;
NotifyPropertyChanged(() => Employees);
}
}
My only issue is that i am using property setter to notify application about the changes made to some value, and according to FxCop this is a bad practice and 'CollectionPropertiesShouldBeReadOnly'. So i want to improve a little bit on that, so tell me some mechanism with which i could use Notify Property changed without using setter.

If your collection property is read-only, you don't need to notify anything that the entire collection has changed to a different one - instead, the event handlers on the collection will be notified of changes within the collection (the addition of items etc).
If you need to be able to change which collection the property refers to within the view model, you could always make the setter private and keep the existing notification mechanism.

The ObservableCollection itself informs about changes happened. So you don't need to raise the PropertyChanged Event. If you think, that it's necessary tho change the collection, then you can delete and add items. Due to the observable pattern, the changes will be anounced.

The fact that you are using a setter means you're trying to replace the instance of the collection with a new object instance. If you just are worried about changes to items in the collection, that's already built into the observablecollection. FxCop is going to complain about the setter whether you had the notifypropertychanges call or not.

Related

How to raise PropertyChangedEventHandler when a sub property is changed in WPF?

I have a property called PriceChangeInPercentWeekly which has other properties like LastOpenPrice, LastClosePrice, etc.
I am changing these continuously. But how can I raise PropertyChangedEventHandler for PriceChangeInPercentWeekly when a sub-property is changed?
When PriceChangeInPercentWeekly itself is changed, I raised it using my custom SetField function. But how can I do this for sub-properties. Because sub-properties do not know the instanced class, right?
PriceChange priceChangeInPercentWeekly;
public PriceChange PriceChangeInPercentWeekly
{
get => this.priceChangeInPercentWeekly;
set => SetField ( ref this.priceChangeInPercentWeekly, value,
"PriceChangeInPercentWeekly"
);
}
Based on the comments, it sounds like you have a issue with properly binding in a collection case. When dealing with collections in MVVM, there are actually 3 seperate kinds of bindings/Change Notifications you need. If any one is missing, you end up getting issues with non-updates pretty quickly:
Whatever class is holding LastOpenPrice, LastClosePrice, PriceChange and the like - it needs change notificaiton on each and every property. Whatever template you use to display that class, needs to properly bind to each of those properties.
You need change notificaiton if anything is added or removed from the Collection. That is the only change notification ObservableCollection<ClassThatHoldsThosePrices> takes care off.
Whatever property exposes the ObservableList<ClassThatHoldsThosePrices> or its Collection View needs change notificaiton as well. ObservableCollections do not support bulk additions. With a big changes you usually have to build a new list in the background, then replace the whole collection.
At this point it usually becomes a question of properly setting up (or automatically having set up) the 3 kinds of bindings. The proper MVVM pattern is not a easy thing to learn and it can not tell if you did it properly, so it is hard to say where the issues could be. About 8 years ago I wrote a short introducing which I think should still be okay-ish for learning the basics: https://social.msdn.microsoft.com/Forums/vstudio/en-US/b1a8bf14-4acd-4d77-9df8-bdb95b02dbe2/lets-talk-about-mvvm?forum=wpf

updating datagrid with BindingList

I've been looking at the difference between a BindingList and an observablecollection and List. From what I've read, it seems like the BindingList is the only collection type that will notify if an object in it has one of its properties changed. I cannot get this to work.
I have a property on a ViewModel called Matches, which returns a BindingList created out of a list of CarMatch objects in another class. (Cars m_Cars = new Cars();) My DataGrid on the View is bound to this Matches property in the VM.
public BindingList<CarMatch> Matches
{
get
{
Return new BindingList<CarMatch>(m_Cars.Matches);
}
}
Now, in the code I change one of the CarMatch object's properties, say.. automaticTrans = true from false. Matches[0].automaticTrans = true. I want to see that change in the DataGrid. Without implementing INotifyPropertyChanged inside of the CarMatch class, is there a way to update the datagrid from the viewmodel? Using INotifyPropertyChanged on Matches does not seem to do it. There is something about this I just don't understand, and could use an example to look at.
CarMatch (not Matches) has to implement INotifyPropertyChanged. But consider using ObservableCollection unless you really need some of the additional scenarios offered by BindingList: with ObservableCollection, INotifyPropertyChanged comes for free. And, more importantly, BindingList doesn't scale well.
try
dataGrid.Items.Refresh();
but keep in mind that is a expensive call if you have lots of data and you call it several times in a short period of time.

C# RaisePropertyChanging?

I'm not sure why I should use RaisePropertyChanging, when notifying the view fx:
private LoggingLvl _myLoggingLvl;
public LoggingLvl MyLoggingLvl
{
get { return _myLoggingLvl; }
set
{
RaisePropertyChanging("MyLoggingLvl");
_myLoggingLvl = value;
RaisePropertyChanged("MyLoggingLvl");
}
}
why is it recommended to use RaisePropertyChanging?
Using INotifyPropertyChanging would allow consuming code a chance to consume the previous value of a property, before a change is applied. This is not frequently going to be useful, but there are cases where it might be: if you imagine a property that represents an "active object," this event would allow you to trigger code that would fire when the object is de-activated.
As a contrived example, consider a UI where the change in value of a field is required to display in a specific way: the old value should "float" off the screen leaving the new value behind. If a model class implemented INotifyPropertyChanging, a viewmodel class could attach to this event in order to cache the old value for use in the float animation. This allows the model class to represent the current state, while the viewmodel can maintain all values necessary to drive the UI.
I have never listened before that RaisePropertyChanging is recommended. You can use it if you need to notify to "outside world" that specified property is going to changed.
This can be useful, for example, when some parts of your application should validate the changing property state against other parameters of your system, so may be also signal that it's not a subject to change, as following Single Responsibility Principle your class may not be aware of states of other instances of types of your application.
The INotifyPropertyChanging interface is used to notify clients, typically binding clients, that a property value is changing.
http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanging.aspx
assume for a long running validation task on your property. hope take 5 seconds for updating the property value. meanwhile some other property are are looking for it these properties are treated under race condition. and wait under a queue and one property changed notification done then the first object will get change to get or set the property value.
let me give you some examples.

ObservableCollection and CollectionView

I'm writing an application that reads data from a local db and display them in a listbox(I'm working in WPF).
I've a DVD object, where its properties are the columns of the db. This DVD object also implements INotifyPropertyChanged. "MyDVDs" is the table that refers to db. Once created these object, I create a class that inherits from ObservableCollection and takes data from "MyDVDs" in the constructor. However I don't need only to add, remove and update data from the listbox, but I also need to sort and filter them. Here is the code for ObservableCollection:
class ObservableDVD : ObservableCollection<DVD>
{
private ICollectionView collection;
public ObservableDVD(MyDVDs e)
{
foreach (DVD d in e.DVDs)
{
this.Add(d);
}
Collection = CollectionViewSource.GetDefaultView(this);
}
public ICollectionView Collection
{
get { return collection; }
private set { collection = value; }
}
}
I wanted to know, this is a good way?? Or can I do better?
In the MainWindow of the project, when Load_Window event fires, I assign the Collection property to listbox.ItemSource(in MainWindow code-behind I declare a private field that obviously refers to an ObservableDVD Object). I have some buttons that allow me to do the operations I tell you before.In the event headler of the buttons, I directly update and modify the ObservableDVD Object, not its property Collection. However, the Collection property also reflects those changes.
Why this behavior occurs?
It's ok for me, but I can't understand why it's happens. Is because of the notifications?
The property Collection has a reference to the view of the ObservableDVD. Being a reference means pointing to the same data in memory.
ObservableCollection Class Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.
The Collection you are specifying is just a "view" of the ObservableDVD collection. Which means that both are really pointing to the same data in the memory, they're not 2 separate things. A "view" can be a subset of items when you apply filters to a collection, for instance.
Otherwise said, your ObservableDVD contains your "Data Table" for the entire dataset while the ICollectionView lets you manipulate which records/objects are visible to the user through custom logic.

How do I pass a property changed event to an ancestor?

I'm sure I am missing some of the basics here so please bear with me.
I have a two objects, a SalesOrder and a SalesOrderLineItem. The lineitems are kept in an Observablecollection<SalesOrderLineItem> of SalesOrder, and if I add line items my databound listView knows about the new items.
Now where I am having a problem is here: The SalesOrder has a read only property called "OrderTotal", which knows what the total price from all the line items combined are.
If I change the quantity, or price of a line item, I don't seem to know how to get change notification to bubble up to "OrderTotal".
Both classes inherit from, and fire INotifyPropertyChanged.
Wham am I missing?
The ObservableCollection only notifies when an Item is added, removed, or when the list is refreshed, not when a property of an Item within the collection changes.
The SalesOrder class needs to be listening to each SalesOrderLineItem's PropertyChanged event.
-
The OrderTotal property could also be dynamic, generating the total each time...
If you feel adventurous, you can try BindableLinq or something similar.
It allows you to expose the result of a query that listens to changes.
But it's not out of beta yet, and I'm not sure it will ever be...
ContinuousLinq is another one, but it does not support Silverlight at all yet.
Other than that, you'll have to listen to each child, and add/remove handlers whenever the collection changes.
public ObservableCollection<TestClass> List
{
get { return _List; }
set {
if (_List!= value)
{
_List = value;
raisePropertyChange("List");
List.ToList().ForEach(i=> i.PropertyChanged+= (o,e)=>
{
//PropertyChanged.Raise(() => List);
raisePropertyChange("List");
//or what ever you want
}
);
}
}
}

Categories