How to bind a WPF control value to a method? - c#

Imagine I have a TextBox that it's Text should be equal to the number of running processes in the machine.
How to make it to update without using timers? Is there a way using Dependency Property or Bindings?

I'm not sure what this has to with binding to a method.
You'd have to keep calling the method on a timer, just the same.
You can set the DataContext to an object that implements INotifyPropertyChanged and exposes a property with the data you want (the getter can, of course, call a method).
Without a timer, you'll need an event to which your data object can subscribe, and then you can raise a notification that the property of interest has changed each time the event fires, and the UI element bound to that property will be updated.

Related

Property Changed event within class

I got a question about events within classes.
I have a whole load of properties within my class and want to fire an event whenever a property is changed. I want to use the changed properties to calculate a result.
One possible option might be adding a call to every single property-set but this is - for my understanding - too q'n'd.
The common approach to realise this would be to implement the INotitfyPropertyChanged interface and raise the PropertyChanged event in every settter method for the properties where you need it.
Then you implement an event handler which reacts to the event and performs the operations needed.
https://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx

INotifyPropertyChanged with a property that's a class?

If I register to be notified of a property's change, it will only notify when the actual property is reassigned. So if I have a property that's a textbox, it won't notify if the text of the textbox changes, right? Is there any way to make it work this way?
If you are interested in specific properties of an object then you should be using a mechanism like INotifyPropertyChanged on the value itself. Unfortunately though in this case TextBox from WinForms doesn't implement INotifyPropertyChanged. In order to listen for changes to its Text property you need to subscribe to the TextChanged event
I have had a hard time imagining why a class would expose a property of type TextBox. Anyhow if you have ended up with such a design, you could simply add two properties, each for the TextBox itself and the text inside and then listen to TextBox's TextChanged event and fire your NotifyPropertyChanged thereupon.
I do feel however that you need to rethink your approach. If your class exposes a property of TextBox type, there should really be places where you actually assign a new TextBox to a class instance and upper layers listening to this change. I don't think that would be the case however. You'd almost certainly be looking for text changes and should therefore expose a property of type string.

Who should call the VIewModel in WPF/MVVM the logical unit or the view?

My question is of "What is the best practice?" type, in a very specific case:
I have a View that contains a listbox of checkboxes.
The listbox.ItemsSource is bound to a collection in the ViewModel (List of Person). And each checkbox.IsChecked is bound to Person.IsSelected.
The check/uncheck of a checkbox activates a 'Refresh' method in the ViewModel, that may or may not re-set the Person.IsChecked of all Persons. That, of course, should notify the UI that Person.IsChecked (might have) has changed.
My question is: Who should be responsible of calling ViewMode.Refresh? Should the UI call the method through an event or Command maybe? Or should the ViewModel subscribe to a proper event in Person.
If the UI is bound to IsChecked, nothing needs to notify it. Or, rather, WPF itself notifies it. That is one of the attractive qualities of MVVM. The view model can simply update its state according to its own set of rules, and the view automatically receives those changes via bindings.
depending on what you mean by "call"
here are the answers
if you mean create:
other ViewModel
anything that's not a View or an Model(because non of them should know your VM)
if you talking about executing a Method:
self execute (e.g. after PropertyChanged, Command, ...)
other ViewModel
anything that's not a View or an Model(because non of them should know your VM)
also important in your case:
you say your list is bounded to Collection
and here you could get some trouble because your View changed the Person.IsSelected which should raise a PropertyChanged for your IsSelected.
Now it will stuck because ObservableCollection doesn't get notified if your Item Property Changed that is a known issue. To fix this problem you need to wire up your INotifyPropertyChanged event to the CollectionChanged event from your ObservableCollection. So it can bubble up to your VM and it can execute his Refresh()
Here you can see an example how you could do it.
I think you have to ask yourself, what is the "refresh" in response to?
If it's in response to the check box physically being clicked, then it's the view's responsibility to call it.
If it's in response to the person being selected, the viewmodel should be watching its own collection for changes to IsSelected.
I agree with MehaJain that the latter is harder to set up, but the alternative breaks up the responsibility of a single unit of work between the layers, meaning that the logic will need to be duplicated in any other function that causes IsSelected to be changed. This includes other views binding to the same information, other commands (say you have a button for running a filter that selects certain people), and tests.
I would prefer to Refresh the View Model through the event or Command.
Because subscribing the collection members is tricky.
Let say you want to use the second approach: Subscribing to the Person class changed event.
Then it can have following disadvantages:
In the constructor of your view model you have to subscribe each "Person" member of your list.
In view model whenever collection gets modified then you have to subscribe/unsubscribe the added/deleted members of that list.
While disposing your view model, you have to unsubscribe the subscribed changed events.
So, this is an over head if you go for subscribing the change event of Person class.

Differenciating selection change depending on call from code or changed by hand

I would like to know if it is possible to make a difference in the event selection change of a combobox.
I want to make a difference between a user that manually click the combobox and changes its value and a change in the selection that i do from code.
ie :
if i click my combobox and change its value by hand, the event is fired
but if i do myCombobox.selectedItem=1 [edit] the events is not fired
Is there an event that has this behaviour in a wpfcombobox ?
If not, do you have any idea on how to do that ?
Thanks
[edit] or if it is the binding of the combobox that changes its value
You are dealing with a couple of different scenarios, both of which are solvable.
1) Don't process SelectedItem requests during databinding. You have at least two options here:
a) Don't add the event handlers to the control until after databinding is complete or the form is loaded (depending on whether or not databinding is automatic or manual).
b) Set a form level property indicating when it is ok to process the SelectedItem event. You will probably want to set this to true after the form is loaded or after the databinding is complete. In your SelectedItem code, don't perform any actions unless this property is true.
2) Process the SelectedItem logic if the SelectedItem is changed programatically. Again, two options:
a) Extract your logic from the SelectedItem event into a method and then call this method when you perform the logic to set the selected item.
b) Create a custom combobox that inherits from the base and add a SetSelectedItem method (for example) to this inherited combo. This method would then raise the SelectedItem method. This would be reusable and you wouldn't have to remember to do 2 pieces of work whenever you set the SelectedItem manually.
Before you change the selecteditem in code, remove the event handler with -=, then add it back afterwards.

Updating a PropertyGrid

How can I have a property grid update automatically when the object in its SelectedObject property changes? I've tried implementing INotifyPropertyChanged in my class but the property grid does not actually show the new propertyies of the object in the background until I click on it.
I've tried subscribing to the PropertyChanged event of my object directly, and calling the Refresh() method of the PropertyGrid when it is envoked. But some of my properties are related. Meaning changing one property may evoke multiple PropertyChanged events. This seems to work fine, but I'm still wondering if there is a cleaner way of doing this through DataBinding. Also I'd like to avoid having the control Refresh multiple times after the user only updated a single property.
So is there a way to get the PropertyGrid to refresh from PropertyChanged events?
Try adding the RefreshProperties attribute to each property that has dependencies:
[RefreshProperties(RefreshProperties.All)]
Now, each time this property changes - it will automatically refresh the other fields.
This is a much cleaner approach than calling the property-grid's "Refresh()" each time.
I don't know if there's a built-in way to do it, but here's a suggestion if you want to avoid multiple calls to Refresh for related properties :
When a PropertyChanged event occurs, start a timer. If the event occurs again before the timer has elapsed, do nothing. In the Tick event of the timer, refresh the PropertyGrid and stop the timer

Categories