Monday, 11 October 2010
Animated Panel version 3
As I wrote before there is annoying problem with AnimatedPanel that it is not possible to animate both removing of item and items movement. Few monthes ago I found very cool features called Behaviours and Interactions (from System.Windows.Interactivity). There is a predefined behaviour there called FluidMoveBehaviour. Using this behaviour it is possible to achive something similar to what AnimatedPanel does. I'm investigating this behaviour and it looks very promising! I hope that next version 3 of AnimatedPanel will leverage on System.Windows.Interactivity and will offer better functionality.
Tuesday, 31 August 2010
Animated Panel explained
In this post I will explain some key moments of the AnimatedPanel. I won't post any code here - just high level explanation.
So, how does that AnimatedPanel work?
Let's start from the beginning, i.e. from WPF layout model.
WPF layout model involves two steps:
1) Measure pass
2) Arrange pass
In measure-pass all visuals tell the parent container what size they want to be. Parent container analyzes that data and then arranges its content (arrange-pass). In the arrange-pass all visuals should arrange itself according to the size they got from the parent (i.e. what size they should be).
And now let's return to AnimatedPanel.
In MeasureOverride method we measure our children telling them that they should fit itself in ItemSize width/height (note that we actually don't care about what size those visuals want to be). We calculate "resSize" and return this size to the parent. It is very important to return valid size. If we would return an empty size (width and heigth equal to zero) then scroll bars would be disabled! (that's right, with exclamation - I don't want my container to be without scroll bars).
In ArrangeOverride we do all the animation logic. We start with checking if our panel is used as an ItemsHost (i.e. inside ListBox or ListView, etc.). And then you can see some strange code that by some reason calls GetHashCode on child's Content. So whythe hell do we need such complexity???? I'll explain it a bit later. After we've got hash code we calculate real position of the element and save it position to the currentMap dictionary (this map contains current positions for all children).
Next step is to determine if this is a new child and to get appropriate transform. First we get TransformGroup from child's RenderTransform (and if child does not have TransformGroup then we create it). Then we look for TranslateTransform inside that TransformGroup. We need TranslateTransform for animating child's movement (why just not to create new TranslateTransform? Because child may have other transforms and we don't want to harm them. That's why we use TransformGroup). If child does not have TranslateTransform then we create it. But, if child does not have TranslateTransform then it may be a completely new child! And this is the place where we need hash code for this child. We simply read previousMap dictionary (it contains positions of all children after previous arrange-pass) and if such hash code exists then we get previous point for this child.
Next step is arrangement of child. We call Arrange method on our child to set child's new location. For our animation we need previous location of the child and for this we have "fromPoint" variable. As soon as we arranged child to its new location we can now animate it. We use "from" animation here. Because "fromPoint" variable contains previous location of the child relative to the child we simply sets the "to" value for animation to zero. We animate child by calling BeginAnimation of our TranslateTransform.
And now I'll explain why we need a hash code.We need hash code for determining previous location of the child. And we actually need hash code of the child's Content because it won't change on sorting or deletion of underlying collection. You may be surprised but when we call Refresh() method on CollectionViewSource's View we will get completely new Children collection in our AnimatedPanel (because View will be rebuilt).
Please note that AnimatedPanel does not expect for objects to be changed. So please take it into account if you want to use this class somewhere.
So, how does that AnimatedPanel work?
Let's start from the beginning, i.e. from WPF layout model.
WPF layout model involves two steps:
1) Measure pass
2) Arrange pass
In measure-pass all visuals tell the parent container what size they want to be. Parent container analyzes that data and then arranges its content (arrange-pass). In the arrange-pass all visuals should arrange itself according to the size they got from the parent (i.e. what size they should be).
And now let's return to AnimatedPanel.
In MeasureOverride method we measure our children telling them that they should fit itself in ItemSize width/height (note that we actually don't care about what size those visuals want to be). We calculate "resSize" and return this size to the parent. It is very important to return valid size. If we would return an empty size (width and heigth equal to zero) then scroll bars would be disabled! (that's right, with exclamation - I don't want my container to be without scroll bars).
In ArrangeOverride we do all the animation logic. We start with checking if our panel is used as an ItemsHost (i.e. inside ListBox or ListView, etc.). And then you can see some strange code that by some reason calls GetHashCode on child's Content. So why
Next step is to determine if this is a new child and to get appropriate transform. First we get TransformGroup from child's RenderTransform (and if child does not have TransformGroup then we create it). Then we look for TranslateTransform inside that TransformGroup. We need TranslateTransform for animating child's movement (why just not to create new TranslateTransform? Because child may have other transforms and we don't want to harm them. That's why we use TransformGroup). If child does not have TranslateTransform then we create it. But, if child does not have TranslateTransform then it may be a completely new child! And this is the place where we need hash code for this child. We simply read previousMap dictionary (it contains positions of all children after previous arrange-pass) and if such hash code exists then we get previous point for this child.
Next step is arrangement of child. We call Arrange method on our child to set child's new location. For our animation we need previous location of the child and for this we have "fromPoint" variable. As soon as we arranged child to its new location we can now animate it. We use "from" animation here. Because "fromPoint" variable contains previous location of the child relative to the child we simply sets the "to" value for animation to zero. We animate child by calling BeginAnimation of our TranslateTransform.
And now I'll explain why we need a hash code.We need hash code for determining previous location of the child. And we actually need hash code of the child's Content because it won't change on sorting or deletion of underlying collection. You may be surprised but when we call Refresh() method on CollectionViewSource's View we will get completely new Children collection in our AnimatedPanel (because View will be rebuilt).
Please note that AnimatedPanel does not expect for objects to be changed. So please take it into account if you want to use this class somewhere.
Monday, 30 August 2010
WPF Animated Panel
I've opened project on codeplex named AnimatedPanel (http://animatedpanel.codeplex.com). The main idea of the project is to create a custom WPF control that allows animating items (while sorting, changing window size, etc.) (inspired by http://razorjack.net/quicksand). Currently there is a second release which has the following features implemented:
1) Animation of items on window resize
2) Animation of items on sorting.
3) Animation of deleted item
Points 2) and 3) are "mutually exclusive" (i.e. you cannot use animated sorting and animated removing together). The reason why you cannot use them both at the same time is technical - I can't find a way ho to do this.
In the nearest future I'm going to implement the following features:
1) Support for Silverlight (if it's possible).
2) Grouping support
You can download the second release by direct link: http://animatedpanel.codeplex.com/releases/51315/download/146135
In the next post I'm going to explain how does that Animation work.
Stay in touch.
:-)
1) Animation of items on window resize
2) Animation of items on sorting.
3) Animation of deleted item
Points 2) and 3) are "mutually exclusive" (i.e. you cannot use animated sorting and animated removing together). The reason why you cannot use them both at the same time is technical - I can't find a way ho to do this.
In the nearest future I'm going to implement the following features:
1) Support for Silverlight (if it's possible).
2) Grouping support
You can download the second release by direct link: http://animatedpanel.codeplex.com/releases/51315/download/146135
In the next post I'm going to explain how does that Animation work.
Stay in touch.
:-)
Friday, 9 October 2009
Why do you love WPF (if you not, then you can stop reading from here)?
I'll try to answer this question.
1) It has a cool name (though Avalon was better).
2) It offers a new layout model.
3) XAML (XAML is not only a WPF feature, but it is really good object-oriented xml-based language).
4) WPF is built on top of DirectX (not WinAPI)
5) Animation support. We can animate whatever we like - resizing, rotating etc.
6) Styling and Templates. All controls were designed to be lookless. It means that we can re-style all controls and give them any appearance we like.
7) 3D support
8) Documents processing
9) Data Binding
10) Media support (playing audio, video, etc.)
This list is far from to be complete (full list you can read on msdn - if you really want to). So the main idea is pretty obvious - WPF is great, isn't it?
I'll try to answer this question.
1) It has a cool name (though Avalon was better).
2) It offers a new layout model.
3) XAML (XAML is not only a WPF feature, but it is really good object-oriented xml-based language).
4) WPF is built on top of DirectX (not WinAPI)
5) Animation support. We can animate whatever we like - resizing, rotating etc.
6) Styling and Templates. All controls were designed to be lookless. It means that we can re-style all controls and give them any appearance we like.
7) 3D support
8) Documents processing
9) Data Binding
10) Media support (playing audio, video, etc.)
This list is far from to be complete (full list you can read on msdn - if you really want to). So the main idea is pretty obvious - WPF is great, isn't it?
Thursday, 17 September 2009
First post
So this is my first post at this blog. I'm going to write here mostly about WPF but sometimes you can find here some notes about cars, football (I'm talking about soccer - not american football :-)) and some other aspects of our life.
Subscribe to:
Posts (Atom)