Any way to get event, when some WPF data binding update occurs? - c#

Any way to get event, when some WPF data binding update occurs?
UPD I'm developing a custom control extending one of standard controls. I need to get notification, when DataContext property of the ancestor control changes, or data binding causes update of any property of the ancestor control.

It sounds like you require: INotifyPropertyChanged to be implemented on your View Model. This obviously depends on your implementation but this is assuming you've followed MVVM.
This then allows you to carry out some work based on the value of a bound property changing (and an event being raised).

As others already mentioned, if your object
implements INotifyPropertyChanged and
the property supports it, register to PropertyChanged and you will be informed about changes.
If you are in a DependencyObject and add your own DependencyProperty, register a DependencyPropertyChangedEventHandler in the metadata to be informed when the property changes-
If you have a DependencyObject and
the property is a DependencyProperty, you can override
OnPropertyChanged. It will be called
every time, a DependencyProperty
value has been changed. You can then filter out the property-changes you are interested in.
If you are outside of a
DependencyObject and want to
listen to a changed value of a DepenendencyProperty, you can use
the DependencyPropertyDescriptor to register for value changes. However take care, using this may produce memory-leaks.

If you're talking about getting a notification from a control perspective (i.e. when a dependency property has been bound to) you can provide a method that will be called passing the value:
public DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
"ItemsSource",
typeof(IList),
typeof(CustomGridControl),
new FrameworkPropertyMetadata(null, OnItemsSourceChanged));
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
e.NewValue;
}

Related

Automatically bind event to a Dependency Properties Value

I am trying to set up a custom user control derived from the ToggleButton control.
I would like to set up two new commands, CheckedCommand and UncheckedCommand.
I have defined the commands as below, and am able to bind to them. And I am firing them via some internal events. It all works great.
However I would like to be able to have these commands disable the button as the usual command interface does with CanExecute. As I understand it I need to use the CanExecuteChanged event and set the IsEnabled Property in here. However when am I supposed to bind this event, I looked at using the PropertyChangedCallback event of the DependancyProperty but then how do I unsubscribe the from any previously bound command.
It all ends up looking a bit convoluted, am I missing something simple or is this just the way it is.
[Description("Checked Command"), Category("Common Properties")]
public ICommand CheckedCommand
{
get { return (ICommand)this.GetValue(CheckedCommandProperty); }
set { this.SetValue(CheckedCommandProperty, value); }
}
public static readonly DependencyProperty CheckedCommandProperty = DependencyProperty.Register(
"CheckedCommand", typeof(ICommand), typeof(ToggleTextButton));
I may not understand your specific requirements but in general I wouldn't do it like this. WPF has been primarily designed to be data-driven, whereas here you're implementing event-driven notification. Events are the old-school WinForms way of doing things and they were added mainly to facilitate an easier transition from WinForms to the new data-bound architecture.
IMO a more "correct" solution here would be to expose a boolean dependency property i.e. basically the same thing as the "Checked" property in checkbox. Users of your control can then bind that one property to a boolean property in their view models whose setter will be called whenever the state changes. A second "Enabled" DP will allow both you and your user to control whether or not the control should be enabled, again similar to how it's implemented in Checkbox.
To ask an obvious question though if it's checkbox functionality you're after then why aren't you just templating checkbox? Do you really need a usercontrol for what it is you're trying to achieve?

PropertyChangedCallback not called

It looks like WPF doesn't always call the registered PropertyChangedCallback procedure of a DependencyProperty. Even if we manually raise PropertyChanged event from the VM, WPF seems to actually evaluate the old and new value of the property before deciding if it would call the callback. So my questions here are:
Why is this so?
What is the workaround?
Details
My ViewModel has a public property define as follows:
Public ReadOnly Property CurrentSelection() As ObservableCollection(Of Object)
My View binds to this property like this (BetterPropertyGrid is a UserControl that wraps a WinForms PropertyGrid in it and has a DependencyProperty named SelectedObjects):
<bd:BetterPropertyGrid SelectedObjects="{Binding CurrentSelection}" />
Now whenever my ViewModel adds or removes objects from CurrentSelection, I manually raise PropertyChanged("CurrentSelection"), but it doesn't seem to update my View.
WPF checks if the property value is actually different from what is was before the change notification was raised. In your case, the same collection instance is returned from the view model property getter, hence the change has no effect.
"Why is this so?": Because old and new property value are equal. In the PropertyChangedEventArgs passed to your PropertyChangedCallback e.OldValue and e.NewValue would reference the same collection instance.
"What is the workaround?": Register a handler for the INotifyCollectionChanged.CollectionChanged event of the SelectedObjects property value, as shown in this answer.

Setting a dependency property of a control in the custom control

I have a infragistics grid that i have inherited from in the my solution . Now i would like to set a dependency property defined in the infragistics grid control in my custom control code behind and not in xaml . How do i accomplish setting the dependency property ?
I was able to set the backing CLR property in my custom control but as expected it didnt trigger off the gridcontrol UI change as expected and hence i m forced to set the dependency property in my custom control .
How exactly do i accomplish this ?
Normally a DependencyProperty is declared like this with CLR property 'wrappers':
public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register(
"Items", typeof(ObservableCollection<string>), typeof(YourControlType));
public ObservableCollection<string> Items
{
get { return (ObservableCollection<string>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
If the Grid that you inherited declared their DependencyProperties like this, then you should be able to use the CLR wrapped properties directly like this:
Items = new ObservableCollection<string>();
Items.Add("Something");
If they didn't do that, then you can see in the wrapped properties how to access them:
anInstanceOfYourControlType.SetValue(ItemsProperty, "some value");
There is of course a chance that they declared internal properties in which case you won't be able to access them, but you should be able to find that out from their online documentation.
You can use DependencyProperty SetValue to set local value of Dependency Property.
dataGridObject.SetValue(DataGrid.ItemsSourceProperty, value);
But in case your DP binded with some CLR property and you want to update it as well, use SetCurrentValue method.
dataGridObject.SetCurrentValue(DataGrid.ItemsSourceProperty, value);

Dependency Property not displaying on initialization

I am not sure if this is even possible, but here is my setup:
I have a customized textbox that is only meant to deal with hotkey selection. In here I have a DependencyProperty that is for the SelectedHotKey.
Then I have a custom control that is a label, the textbox, and a button. This control also exposes a DependencyProperty of the same name as the TextBox, and it merely ties to the TextBox via:
SelectedHotKey="{Binding ElementName=Main, Path=SelectedHotKey, Mode=TwoWay}"
With this dependency property, I am looking to set the textbox's SelectedHotKey, which will change the Text appropriately.
I am then using that user control and binding to my ViewModel.
I have all of this working except for the initialization case.
When my ViewModel is already set up and passed to the UserControl in the binding, that initial setter does not even get hit, so it does not propogate down through my controls. I thought about putting in a PropertyMetaData method, however that is a static method and I do not have access to my instance textboxes.
Any ideas? Let me know if I need to clarify further.
Don't put code logic in the CLR property wrapping the dependency property. As you have already seen, there is no guarantee they will ever be called since the framework can call SetValue directly on the dependency property.
You're in the right track: you have to use the dependency property metadata. Access the instance by using the first parameter of the property changed callback.
DependencyProperty SomeProperty = DependencyProperty.Register(
"Some",
propertyType,
ownerType,
new FrameworkPropertyMetadata(defaultValue, OnSomePropertyChanged));
static void OnSomePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
// "d" is your instance here, cast it to the required type
}

Understanding how DependencyProperty works and is implemented

The Silverlight/WPF DependencyProperty enables data binding and indicates when the property has changed in value, without implementing INotifyPropertyChanged. My question is on how does this work at the low level - how does DependencyProperty or DependencyObject perform this change notification when neither DependencyObject, DependencyProperty, nor DispatcherObject define any events. Would this have something to do with the DispatcherObject.Dispatcher property?
Dependency properties, or the DependencyObject class, do not natively
support INotifyPropertyChanged for purposes of producing notifications
of changes in DependencyObject source property value for data binding
operations.
This excellent clarification was taken word-for-word from:
http://msdn.microsoft.com/en-us/library/ms752914.aspx
http://msdn.microsoft.com/en-us/library/ms753358.aspx
Dependency properties are tightly integrated with the binding system internally. So instead of "notifying that the property changed", the code that sets the dependency property can call directly into the binding system and tell it to updated.
Similarly, things like inherited/attached properties can be updated on any descendant elements and/or the layout/measure/arrange can be updated. It can even tell any triggers (in Styles or ControlTemplates) to be reevaluated.
The Dispatcher isn't really related, but may be used during the process.
So in short, it's baked into WPF/Silverlight.
Well, when you register a DependencyProperty you provide a callback to be called when the value changes.
Here you have more details. I don't think anything else is public about the internals of WPF. I might be wrong.

Categories