I have a custom Control with dependency property attached by its parent and i need to implement some hook that will be triggered on all attached property changes. In WPF it was rather easy but i have no idea how this can be achieved in WinRT environment.
For example, i have Control with attached property X and its parent is GraphArea. So attached property for Control is GraphArea.X.
Please give me some clues, thanks :)
Found the way to do this though not exactly as i wanted to. Instead of hooking to X change inside every Control i've hooked to attached property changed callback of the parent.
Additionaly, i've implemented new interface for all children that must receive notification when this property changes. And as i've implemented interface methods as explicit interface implementations they are not be visible from derived classes (which is good as this operation must be internal).
Another solution is to make code-behind binding between dependency property and attached property and define OnChanged callback for DP. But in WinRT this approach only works for internal Attached Properties (not the custom created).
Related
I am developing a custom control for Windows Phone 8, which is derived from ItemsControl, will have many child objects(another custom class). It needs to have an Attached Property IsMinonAxis which should be set only once by one of the child, and not more than once. So the below code will be a problem I want to avoid.
<WPGraphControl:GraphControl>
<WPGraphControl:GraphLine GraphDataPoints="{Binding SpeedPoints}" WPGraphControl:GraphControl.IsMinonAxis="True" />
<WPGraphControl:GraphLine GraphDataPoints="{Binding AltitudePoints}" WPGraphControl:GraphControl.IsMinonAxis="True" />
</WPGraphControl:GraphControl>
The problem is attached properties are attached to child controls, and not to the parent.
In the PropertyCHangedCallback (registered as part of RegisterAttached as part of PropertyMetadata) I can get the child object for which the property is being set, but I can't access the actual control instance (this) to be able to validate the whole collection of child controls as its a static method common across all instances .
One option I am thinking is to have another attached property (internal) which will be attached when the child controls are added, and then use that property to get to parent inside the callback, and fire the validation logic. It sounds like a overly complicated logic to me.
Could you please suggest what is the best way to handle situations like this?
Might be easier to have a non-attached property on GraphControl that takes a Element to be used. Its been a while since I did WinPhone XAML, but in WPF this would look something like:
<wpgc:GraphControl MinorAxis="{Binding ElementName=Foo}">
<wpgc:GraphLine x:Name="Foo" />
<wpgc:GraphLine x:Name="Bar" />
</wpgc:GraphControl>
Since you can only assign a single value to the property, then this would ensure that only one is set.
I am doing an app in C#, Windows Forms.
In this app I have a main form that has several Elements in it. This "Element" class is inherited by others ("ElementLabel","ElementPicture","ElementGraph").
At some point i might want to change in "batch" mode some property of several elements, whichever they are. For example, I might want to change the property "Value" of all the selected elements.
The problem is, for example, when the property "Value" is changed in the parent class, I also want to change the property "Text" of a "Label" that exists in the child class "ElementLabel". I've seen a lot of topics on changing the parent through the child, but not otherwise.
Am I missing something here or do I just have a bad design and a situation like this isn't even supposed to happen?
Thanks in advance
Well its hard to say what the best option is without knowing more about your architecture, but subclasses can intercept events in the parent class by overriding methods. For example, in your ElementLabel class:
public override void set(String key, object newValue) {
if (key.Equals("Value"))
set("Text", "New label text!");
base.set(key, newValue);
}
If you want a more general solution, you could include an observer pattern in your parent class; see the wikipedia page
You could use for the data a class (or classes) that implements INotifyPropertyChanged.
Then you would have to pass to the child controls references to a "master" property that you used to control the state. (It would be ideally used by a Controller class.) (I'll refer to this object as the "master property object".)
Each of the child controls would subscribe to the PropertyChanged event.
Then when the Controller changes the value of one of the master property object's properties, it will raise the PropertyChanged event, and each interested child can respond appropriately.
This approach helps to decouple the controller from the views.
The sequence is:
Before creating the child controls, create the master property object. Keep a reference to this in the Controller or Main Form (if you're using that as a controller).
Pass to each child control that needs it, a reference to the master property object.
Each child control should subscribe to the master property object's PropertyChanged event.
Write an appropriate handler for each child. It will have access to a reference to the master property object, so it will be able to see the new values of any properties.
When a property needs to be changed, the Controller simply sets the property as desired. The property setter implementation should raise the PropertyChanged event, and that will notify all the interested child controls, who will update their UI in response.
[EDIT] This is in fact an implementation of the Observer pattern that Reyan mentioned above.
I am trying to come up with a solution for the following problem:
I have a DateTimeRange class which contains 3 properties:
Start: DateTime
End: DateTime
Length: Length (=End-Start)
This class is used throughout my project as dependency property on various controls. This values are mutable, for example, if the Start changes, the End will be moved with the same offset (keeping the same Length).
My problem is that in code that listens for updates of the range, does not recieve an event when any of the properties have changed, only when the complete object is replaced.
I want to let the DateTimeRange class notify the user that the whole object has changed when a property is changed, not just one property.
I have tried to make DateTimeRange an immutable struct. But this makes two way DataBinding to any of it's properties impossible.
Does anybody have a suggestion how to do this? IMO this problem is very frustrating, as the same problem happens with Margins for example (you cannot bind to Margin.Left of a control).
The framework does not really support this requirement. The approach I would take would be to make DateTimeRange implement INotifyPropertyChanged, raising the event whenever any of its properties change. On a class that has DateTimeRange as a dependency property add / remove handlers for the INotifyPropertyChanged as the property changes. Within your handler for this event you can then perform the action you require.
Note, you could make DateTimeRange a DependencyObject, which would allow you to create two way bindings to its properties.
I have an ObservableCollection that's binded to a WPF ListView, and all the values appear correct. But how can I get a notification when something that has a 2-way binding changes?
Should I use INotifyPropertyChanged just like in Winforms? Or are there better practices to do these?
I saw some people suggesting using dependency properties online, but not sure if that's what should do.
If the class I want to add a property is a DependencyObject, I generally add a DependencyProperty. If the class is a POCO (plain old clr objects), then I implement INotifyPropertyChanged.
In generall, all my business objects are POCOs and therefore I use INotifyPropertyChanged. In the WPF world, I mostly use DependencyObjects (view models, custom controls, UserControls...) and therefore they are DependencyProperties. An exception are ViewModels representing items (to be used as items in an items source). In this case I think DependencyProperties are not very practical (Because Equals() and GetHashCode() of DependencyObjects are sealed and DependencyObject is thread-dependent).
If your class already is a DependencyObject, using DependencyProperties may give you some nice advantages: You don't have to back every value, a powerfull inheritance system, default-values, property changed callbacks per property, value coercion ... (I like DependencyProperties probably more than other people them like :)
Conclusion:
Based on the title of your question: How to get notified when something changes in a WPF window?, my way would be to add a DependencyProperty and not a clr-property because the Window is a DependencyObject. By the way, Visual Studio has a nice Snippet to create DependencyProperties.
There are really two scenarios:
1) Notifying the UI when a piece of data changes-either in the ViewModel or a Model that is bound to some UI elements (usually due to a data binding). In this scenario you'd use INotifyPropertyChanged.
Example: you have a Person object that binds it's Name to a TextBox. Person needs to implement INotifyPropertyChanged and the appropriate code needs to be attached to the Name Property's setter.
2) Creating custom UI elements where you'd want data to be bound. In this case, you'd use custom dependency properties.
Example: you have a custom UI element that spins when a certain condition is met. So you create an IsSpinning dependency property that you can bind to your ViewModel's IsLoading property. The custom control then uses the IsSpinning property to modify its behavior.
I hope that was clear...
You are right. You can use INotifyPropertyChanged or you can implement dependency properties. Personally I prefer INotifyPropertyChanged, it's more light and easyer to implement than dependency property.
I've generally used INotifyPropertyChanged for my data objects.
DependencyProperties can only be implemented on framework elements I believe.
Edit: I take that back... DependencyProperties can only be implemented on DependencyObjects (A FrameworkElement is an example of that as it derives from UIElement which derives from Visual which derives from DependencyObject).
If you have a UserControl, you may wish to implement a Dependency Property so you can Bind that Property (in XAML) to some other property. You could not do this scenario with INotifyPropertyChanged.
We use the ContentControl and other containers stuff in WPF. I need the notification with the new child control is added to the container. What is the best way to get the newly created control within parent?
The ContentControl only contains a single child which is attached via the ContentControl.Content property. You can hook the ContentControl.OnContentChanged to discover when the value of this property is updated.
The cleanest way is to derive from those control and override the methods that report the changes you are interested in. For example derive from ContentControl and implement OnContentChanged. This approach may not appeal to you.
If you want to detect changes in the child or children of controls without deriving from them, you can observe that such changes will affect the layout and so you can hook the LayoutUpdated event. The problem with this approach is that you need to keep track of the children that were previously added yourself by inspecting Child or Children looking for changes. You also have to be careful not to hang onto references to former children lest you create a memory leak. But it can be done.