Can you animate a custom dependency property in Silverlight? - silverlight

I might be missing something really obvious. I'm trying to write a custom Panel where the contents are laid out according to a couple of dependency properties (I'm assuming they have to be DPs because I want to be able to animate them.)
However, when I try to run a storyboard to animate both of these properties, Silverlight throws a Catastophic Error. But if I try to animate just one of them, it works fine. And if I try to animate one of my properties and a 'built-in' property (like Opacity) it also works. But if I try to animate both my custom properties I get the Catastrophic error.
Anyone else come across this?
edit:
The two DPs are ScaleX and ScaleY - both doubles. They scale the X and Y position of children in the panel. Here's how one of them is defined:
public double ScaleX
{
get { return (double)GetValue(ScaleXProperty); }
set { SetValue(ScaleXProperty, value); }
}
/// <summary>
/// Identifies the ScaleX dependency property.
/// </summary>
public static readonly DependencyProperty ScaleXProperty =
DependencyProperty.Register(
"ScaleX",
typeof(double),
typeof(MyPanel),
new PropertyMetadata(OnScaleXPropertyChanged));
/// <summary>
/// ScaleXProperty property changed handler.
/// </summary>
/// <param name="d">MyPanel that changed its ScaleX.</param>
/// <param name="e">DependencyPropertyChangedEventArgs.</param>
private static void OnScaleXPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyPanel _MyPanel = d as MyPanel;
if (_MyPanel != null)
{
_MyPanel.InvalidateArrange();
}
}
public static void SetScaleX(DependencyObject obj, double val)
{
obj.SetValue(ScaleXProperty, val);
}
public static double GetScaleX(DependencyObject obj)
{
return (double)obj.GetValue(ScaleXProperty);
}
Edit: I've tried it with and without the call to InvalidateArrange (which is absolutely necessary in any case) and the result is the same. The event handler doesn't even get called before the Catastrophic error kicks off.

It's a documented bug with Silverlight 2 Beta 2. You can't animate two custom dependancy properties on the same object.

I would try commenting out the InvalidateArrange in the OnPropertyChanged and see what happens.

I hope it's not bad form to answer my own question.
Silverlight 2 Release Candidate 0 was released today, I've tested this problem on it, and it appears to have been fixed. Both Custom DPs in my test panel can now be animated properly, so the app is behaving as expected. Which is nice.
Note that this RC is only a developer-based RC so the standard build of Silverlight hasn't been updated. I'd expect it to be fully released in the next month, though.

Related

Order In Chaos Of Control Initialization Steps

I would like to know when is actually what happening inside initalization process of controls when I start a WPF application?
When are DP initalized? When Binding? When does DataContext get set? Is DataContext avaialbe in constructor of a control? Is there any kind of order?
I realized I ran into a trap that once I set a value on getter/setter of a DP inside constructor of a control the DP value gets updated but immediately also the values gets rolled back to default value which was null.
So my guess is that contructors get initalized first and then dependency properties.
Can somebody help me out with this?
Edit: Just for Rachel. The dp receives the value 234 and immedialty rolls back to null. I think its because constructor gets called first and then subsequently the initalizing of dps happens which sets dp back to null because null is default value. Am i thinking wrong about this? What is the order of initalization steps of a control or dependency object.
class MySuperDuperCoolClass : ContentControl
{
public MySuperDuperCoolClass()
{
InitalizeComponents();
this.MySuperDuperProperty = "234";
}
public string MySuperDuperProperty
{
get { return (string)GetValue(MySuperDuperPropertyProperty);}
set { SetValue(MySuperDuperPropertyProperty, value);}
}
public static DependencyProperty MySuperDuperPropertyProperty =
DependencyProperty.Register("MySuperDuperProperty", typeof(string), typeof(MySuperDuperCoolClass),
new PropertyMetadata(null));
}
I find the DispatcherPriority Enum useful for recalling the exact event order:
Send
Normal - Constructors run here
DataBind
Render
Loaded
Background
ContextIdle
ApplicationIdle
SystemIdle
Inactive
Invalid
Input
As you can see, Constructors get run first, followed by data bindings.
DependencyProperties get initialized when the object gets created, just like any other property, so that would occur prior to the constructor being run so the property exists in the constructor.
Setting the DataContext property or other DependencyProperties works just like any other property you are setting. If you set them with a binding, they'll get evaluated after the constructor. If you set them in the XAML, they'll get set in the Constructor. If you set them in the Loaded event, they'll get set after everything has been constructed, bound, and rendered.
You also might find this SO answer useful:
Sequence of events when a Window is created and shown
As requested, here is the sequence of major events in WPF when a
window is created and shown:
Constructors and getters/setters are called as objects are created, including PropertyChangedCallback, ValidationCallback, etc on the
objects being updated and any objects that inherit from them
As each element gets added to a visual or logical tree its Intialized event is fired, which causes Styles and Triggers to be
found applied in addition to any element-specific initialization you
may define [note: Initialized event not fired for leaves in a logical
tree if there is no PresentationSource (eg Window) at its root]
The window and all non-collapsed Visuals on it are Measured, which causes an ApplyTemplate at each Control, which causes additional
object tree construction including more constructors and
getters/setters
The window and all non-collapsed Visuals on it are Arranged
The window and its descendants (both logical and visual) receive a Loaded event
Any data bindings that failed when they were first set are retried
The window and its descendants are given an opportunity to render their content visually
Steps 1-2 are done when the Window is created, whether or not it is
shown. The other steps generally don't happen until a Window is
shown, but they can happen earlier if triggered manually.
Edit based on code added to question
Your DependencyProperty.Register method looks funny to me. The signature of the method doesn't match any of the overloads for that method, and you're using what appears to be a custom UIProperty class to set the default value instead of the normal PropertyMetadata.
I can confirm that if your code runs as expected with a normal DependencyProperty.Register signature, so the likely cause of your problem is either somewhere within your custom code, or its with how you are using/setting the property.
The code I used for a quick sample test is this:
public partial class UserControl1 : ContentControl
{
public UserControl1()
{
InitializeComponent();
this.TestDependencyProperty = "234";
}
public string TestDependencyProperty
{
get { return (string)GetValue(TestDependencyPropertyProperty); }
set { SetValue(TestDependencyPropertyProperty, value); }
}
public static DependencyProperty TestDependencyPropertyProperty =
DependencyProperty.Register("TestDependencyProperty", typeof(string), typeof(UserControl1),
new PropertyMetadata(null));
}
and the XAML is
<ContentControl x:Class="WpfApplication1.UserControl1"
x:Name="TestPanel" ...>
<Label Content="{Binding ElementName=TestPanel, Path=TestDependencyProperty}"/>
</ContentControl>
In WPF you are setting default values for DP with PropertyMetaData not via constructor.
public partial class UserControl1 : ContentControl
{
public UserControl1()
{
InitializeComponent();
}
public string TestDependencyProperty
{
get { return (string)GetValue(TestDependencyPropertyProperty); }
set { SetValue(TestDependencyPropertyProperty, value); }
}
public static DependencyProperty TestDependencyPropertyProperty =
DependencyProperty.Register("TestDependencyProperty", typeof(string), typeof(UserControl1),
new PropertyMetadata("234"));
}

Add Dependency Property to existing .NET class

IN a WPF project I have a bunch of controls in which I would like to be able to set individual Margin properties and conserve the other values. So, I would like to avoid setting the complete margin to a new Thickness (Margin="0,5,0,15"). Because many margin's are set from styles etc. But in individual cases I would like to deviate from the generic styles for certain controls.
I thought, why not register a couple of new dependency properties on the .NET class FrameWorkElement like so (for example only MarginLeft is shown):
public class FrameWorkElementExtensions: FrameworkElement
{
public static readonly DependencyProperty MarginLeftProperty = DependencyProperty.Register("MarginLeft", typeof(Int16?), typeof(FrameworkElement), new PropertyMetadata(null, OnMarginLeftPropertyChanged));
public Int16? MarginLeft
{
get { return (Int16?)GetValue(MarginLeftProperty); }
set { SetValue(MarginLeftProperty, value); }
}
private static void OnMarginLeftPropertyChanged(object obj, DependencyPropertyChangedEventArgs e)
{
if (obj != null && obj is UIElement)
{
FrameworkElement element = (FrameworkElement)obj;
element.Margin = new Thickness((Int16?)e.NewValue ?? 0, element.Margin.Top, element.Margin.Right, element.Margin.Bottom);
}
}
}
But this property doesn't come available in code-behind or in XAML. I can understand it somehow, because this dummy class is never instantiated or whatsoever. Tried to make it a static class but then you can't derive from FrameWorkElement (which I need for the GetValue and SetValue methods).
I couldn't find any resource on the net that treats the more generic question: Can you add dependency properties to exiting .NET classes?
Any help / wise advice is appreciated.
BTW: a solution for changing only one component of a Margin (Thickness) is also appreciated ;)
If you want to define a property to be set on an object that you do not own then you want to define an attached property in which case you would use the RegisterAttached method instead of Register. Also you would define the property as static get/set methods and not as an instance property since this would not be set on an instance of your object but on some unknown frameworkelement. The help topic from the link shows an example. The links in the other comments also provide more information and examples.
If you want change only one component of a margin use in xaml Margin="1,2,3,4", where 1 - left, 2 - top, 3 - rigth, 4 - bottom

Using a WPF window as customized modal import dialog fails on DependencyProperties

I want to create a customized import dialog and therefore I created a window with some stuff. In order to make this import dialog modal, I'm using the ShowDialog() method. Up to now everything works as expected. My code looks like:
var dialogresult = new MyImportDialog().ShowDialog();
if(dialogresult.HasValue && dialogresult.Value)
{
Console.WriteLine("Import");
}
But when I try to use this dialog twice, got a ArgumentException because my static DependencyProperties got registered a second time. So I tried not to delete my import dialog and use it a second time.
private MyImportDialog _myImportDialog;
private void OnImportClick(object sender, RoutedEventArgs e)
{
if (_myImportDialog== null)
_myImportDialog= new MyImportDialog ();
var dialogresult = _myImportDialog.ShowDialog();
if(dialogresult.HasValue && dialogresult.Value)
{
Console.WriteLine("Import");
}
}
Now I got an InvalidOperationException(Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed.). But the ShowDialog method has an remark: "Opens a window and returns only when the newly opened window is closed."
So my next idea was to register for the closing event in my import dialog and then unregister my DependecyProperties. Unfortunately there is no official way doing this. The only thing I found was this: Any way to un-register a WPF dependency property?.
But the solution is (in my opinion) a little bit dirty and the author warned not to use this code in productive environment.
So, is there another more cleaner solution to use a modal window twice?
Thanking you in anticipation.
Edit:
This code shows one Dependency Property I'm using:
public DependencyProperty ClearProperty =
DependencyProperty.Register("Clear", typeof (bool),
typeof (MyImportDialog),
new PropertyMetadata(true));
/// <summary>
/// Indicates whether view should be cleard before importing new image stack.
/// </summary>
public bool Clear {
get { return (bool) GetValue(ClearProperty); }
set { SetValue(ClearProperty, value);}
}
It sounds like your static dependency properties are not defined as static members. Otherwise they would only be initialized when the static initializer was executed (i.e. the first time the class was referenced). Can you paste the DependencyProperty.Register code? DependencyProperty fields are supposed to be declared statically.
public static DependencyProperty ClearProperty =
DependencyProperty.Register("Clear", typeof (bool),
typeof (MyImportDialog),
new PropertyMetadata(true));

When to use a WPF Dependency Property versus INotifyPropertyChanged

Do folks have any guidance on when a simple .NET property that fires INotifyPropertyChanged.PropertyChanged is sufficient in a view model? Then when do you want to move up to a full blown dependency property? Or are the DPs intended primarily for views?
There are a few approaches:
1. The dependency property
While you using the dependency property it makes the most sense in elements-classes that have a visual appearance (UIElements).
Pros:
WPF do the logic stuff for you
Some mechanism like animation use only dependency property
'Fits' ViewModel style
Cons:
You need to derive form DependencyObject
A bit awkward for simple stuff
Sample:
public static class StoryBoardHelper
{
public static DependencyObject GetTarget(Timeline timeline)
{
if (timeline == null)
throw new ArgumentNullException("timeline");
return timeline.GetValue(TargetProperty) as DependencyObject;
}
public static void SetTarget(Timeline timeline, DependencyObject value)
{
if (timeline == null)
throw new ArgumentNullException("timeline");
timeline.SetValue(TargetProperty, value);
}
public static readonly DependencyProperty TargetProperty =
DependencyProperty.RegisterAttached(
"Target",
typeof(DependencyObject),
typeof(Timeline),
new PropertyMetadata(null, OnTargetPropertyChanged));
private static void OnTargetPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Storyboard.SetTarget(d as Timeline, e.NewValue as DependencyObject);
}
}
2. The System.ComponentModel.INotifyPropertyChanged
Usually, when creating a data object, you’ll use this approach. It is simple and neat solution for Data-like stuff.
Pros and Cons - complementary to 1. You need to to implement only one event (PropertyChanged).
Sample:
public class Student : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
}
private string name;
public string Name;
{
get { return name; }
set {
name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
3.PropertyNameChanged
Rising an event for each property with specified name(f.e. NameChanged). Event must have this name and it is up to you to handle/rise them. Similar approach as 2.
4. Get the binding
Using the FrameworkElement.GetBindingExpression() you can get the BindingExpression object
and call BindingExpression.UpdateTarget() to refresh.
First and second are the most likely depending what is your goal.
All in all, it is Visual vs Data.
As far as I know, DependencyProperty is only required when you need
PropertyValue inheritence
you need to allow the property to be set in Style setters
Use animation for the property
etc.
These features will not be available with normal properties.
DependencyProperty is required if you want to allow a binding to be set on the property. Usually this is for custom UIElements you create. You want to allow people to be able to bind data to your UIElements.
<local:MyUIElement MyProperty={Binding Path=SomethingToBindTo} />
To do this requires that MyProperty is a dependancy property
The main problem I see with INotifyPropertyChanged is if you viewmodel is complex containing many nested types it appears that you have to bubble the PropertyChanged event up through the hierarchy.
As the other answers have already said enough about when to create dependency property. i.e.
PropertyValue inheritence
you need to use binding on a property
Use animation for the property
The one more perspective/question on this is "In a WPF application is makes sense to create dependency properties in a control cause they are likely to change during user interaction like Height,width, text,content, background etc but what about other classes like Behaviors Classes(Non UI classes). Do properties in those classes need to be a dependency property?"
I won't say for very absolute or emphasis on some set of rules here but you should create your properties as DP. As from design perspective if a property is DP it's always in default form of WPF to use/bind.i.e.
As a DP is much more fast/natural in reflecting changes compare to a normal CLR property.
A DP has validation mechanism to validate the value assigned and a default structure to revert the value.
A DP has Coerce value callback to control the limits of property.
A DP has meta data associated with it unlike CLR property.
In terms of practices I've seen people doing many mistakes in nested bindings and then raising changes these kind of faults doesn't happen with a DP cause of it's design and compatibility of raising change itself. So with a little extra syntax you put a flexibility/performance/ easeness to your application. So go for it wherever affordable.
Still can't say sure for ViewModel classes/other helper classes. will update the answer if found convincing reasons in future.
Just a post worth reading on this topic

Dependency Property In WPF/SilverLight

I have searched on google about how to get started with the dependency property used in WPF/silverlight but didn't get any idea of the dependency property, can any one tell me about it , from beginner point of view, so that I get some idea about it and use it in my project
thanks in advance.
Can any one give me link or code example of simple application which explain in simple manner what is dependency Property is ???
I will be very thankfull
I find that implementing a DependencyProperty often involves four parts:
The DependencyProperty itself
Property with get and set
Static changed handler
Instance change handler
You can add a dependency property to a UserControl so that you can data bind to something in the DataContext where the UserControl is instantiated. For example you could add a property to a SoUserControl:
#region SampleProperty // Demo for SO 2424526
public static readonly DependencyProperty SamplePropertyProperty
= DependencyProperty.Register("SampleProperty", typeof(int), typeof(SoUserControl), new PropertyMetadata(OnSamplePropertyChanged));
/// <summary>
/// Demo for SO 2424526
/// Gets or sets dependency property.
/// </summary>
public int SampleProperty
{
get { return (int)GetValue(SamplePropertyProperty); }
set { SetValue(SamplePropertyProperty, value); }
}
/// <summary>
/// Handld changes to SamplePropertyProperty by calling a handler in the associated object.
/// </summary>
/// <param name="obj">object the property is associated with</param>
/// <param name="e">details of change</param>
static void OnSamplePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as SoUserControl).OnSamplePropertyChanged(e);
}
/// <summary>
/// Handle changes to the SamplePropertyProperty dependency property.
/// </summary>
/// <param name="e">details of change</param>
private void OnSamplePropertyChanged(DependencyPropertyChangedEventArgs e)
{
int SamplePropertyNewValue = (int)e.NewValue;
// do something with the internal logic of the control
}
#endregion
From my use with Dependency Properties. They become most important when binding. When you bind to display a regular property, the initial binding will work great, however, the UI will not always update when the property changes, in which case you could implement INotifyPropertyChanged on your class and raise a the NotifyPropertyChanged event, but a Dependency Property will update for you without implementing INotifyProperty Changed.
Triggers is another big one. If you wish to create a Trigger to fire off a WPF Animation whenever one of your properties is set to a certain value... then you need to be triggering off of a dependency property.
DepenedencyProperties can only be implemented on types that derive from DependencyObject.
UIElement derives from Visual which derives from DependencyObject, so most properties from .Net controls are dependency properties already. And when creating and registering my own DependencyProperties it's usually on my custom UserControls as that inherits from UIElement.
It was very frustrating for me when I first tried to create a dependency property on one of my regular classes (you're better off using INotifyPropertyChanged here)
Links:
http://msdn.microsoft.com/en-us/library/ms752914.aspx, http://www.wpftutorial.net/DependencyProperties.html
Have a look at Luis Abreu's blog :http://msmvps.com/blogs/luisabreu/
He's got a lot of info there about dependecy properties and how to use them.
I think you can compare it to the keyword yield.
it allows you to generate a lazy list, or an infinite generator.
every time it's needed one item is requested from that list, and the code continue with the flow.
A dependency property is the same idea for values or content. it computes the needed value, lazily, based on the other values it depends on.
it can cache the value, and when the underlying parts are "dirty", that is, something changed, it will propagate -- invalidate -- all the levels that depend on it.
the object needs to have the facilities of DependencyObject to participate (that is, so the engine will know about it, to introduce it to the chain.)
the mechanism is generic and unfixed, there isn't just one interface to comply with.
but it's somewhat more complex than what I said.
I have found a good explanation, to wire my understanding, in the following blog post:
http://blog.hackedbrain.com/2004/12/04/understanding-dependencyobject-and-dependencyproperty/
You should read a book, for starters.
I have read WPF In Action With Visual Sutdio 2005 from Manning.
As an answer for the negative punctuation just given to me, Dependency Property is part of a bigger plan called WPF and one can't understand Dependency Properties without the basics.
Therefore i think it's a waste of time to try to understand only what is a Dependency Property because i fear one will end up using it incorrectly.
Also, MSDN website has free information about WPF and Dependency Property.

Resources