I'm trying to achieve a custom transition animation with a shadereffect on an image.
I'm using a system i made for specifying easing Bézier functions graphicaly and i process all the spline data in a class called Spline.
i'm animating a time property send to a Spline's static method to compute the Bézier data for easing.
then i get the computed value that i send to the Time property of my shader effect
but i can't use beginAnimation on this transition because the class playing the animation is a non-UI one and already inheriting from an abstract class.
If i want to use beginAnimation, i have to make the abstract class inherit from dependencyObject to use a dependency property as parameter of BeginAnimation but i get this error
this.BeginAnimation(TimeProperty, anim);
'MyClass' doesn't contain a definition for BeginAnimation and no extension method BeginAnimation accepting a frist argument of type 'MyClass' could be found (are you missing a using directive or an assembly reference)
all this dependency/Animatable system doesn't fit my needs since i'm not working on the ui directly and i'm totally stuck now
Any idea?
(I used a dispatcherTimer to do the trick but when the animation finish, i can see the background color of my application during half a second and then my second image finally shows up but i don't want this behavior since it will be marketed...)
Use a KeyFrame Animation. You can add single Frames to it. As example you can hide something every 2nd keyframe.
I finally used a Storyboard to achieve this, using the Dependency object inheritance on my abstract class.
And even if it's not great to use the Sotryboard/dependencyProperty system on a non-UI object(in my opinion), it works.
I have a storyboard to animate a DependencyProperty named Time in MyClass from 0 to 1.
In the PropertyChangedCallback of Time, i compute my new time value depending on my custom spline easing function, and then affect it to the Progress property of my Shader.
thanks for concern anyway.
Related
At what time of object lifecycle are bindings resolved for the first time?
It is a simple question but I cannot find any information neither in books nor through Google.
It's not that simple actually, you won't get a straight answer for this question. It depends on the context.
Here are two simple examples :
If the bounded property is owned by a WPF control that is not inside a ControlTemplate, the binding will most likely be resolved for the first time when the UpdateLayout method is called for the first time, if the DataContext is already set.
If the DataContext was not set, it will try to be resolved after the control is Loaded: see the DataBindEngine.RequestRun() below
private void RequestRun()
{
base.Dispatcher.BeginInvoke(DispatcherPriority.DataBind, new DispatcherOperationCallback(this.Run), false);
base.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new DispatcherOperationCallback(this.Run), true);
}
If the bounded property is owned by a WPF control that is inside a ControlTemplate however, it will be resolved for the first time during the first layouting pass that will trigger an ApplyTemplate and lead to resolving the binding.
Those are only specific examples, if you want to fully understand the binding mechanisms, you should use reflector to take a look at MS.Internal.Data.DataBindEngine and System.Windows.Data.BindindExpression classes. Those are the classes responsible for pushing the correct data when using bindings on dependency properties.
I want to do some rendering in WPF so that I found the hints in MSDN which suggest to use the light-weight DrawingVisual to make a rendering object (e.g. Triangle)
Whenever a property (e.g. color, coordinates) of the rendering is changed, it will render again.
(e.g. RenderOpen(); drawingContext.Draw(.......) ........)
Then I replace the rendering object with UIElement instead of DrawingVisual for the base class with other the same.
And I found that I only render one time no matter how I change the property. Still, I call InvalidateVisual() whenever a property is changed.
Eventually, I found that the rendering performance is much better than DrawingVisual.
Is it the truth?
I'm doing custom rendering in a Decorator subclass. Our rendering requires creating complex geometries which only neded to be re-created when the actual rendered size changes. As such, I have moved the geometry creation into its own function called UpdateGeometry which creates, then freezes the geometry for use in OnRender. This new function only needs to be called in response to a change in ActualWidth or ActualHeight.
Even better, it looks like we should be able to simply override OnRenderSizeChanged, which according to the documentation states...
"When overridden in a derived class,
participates in rendering operations
that are directed by the layout
system. This method is invoked after
layout update, and before rendering,
if the element's RenderSize has
changed as a result of layout update."
However, regardless if I'm using the override or listening to the property change notifications of ActualWidth and ActualHeight, my logging consistently shows OnRender as happening first! Um... Wha??
To be sure it wasn't something I was doing in my code, I created a bare-bones test decorator subclass and added logging there, both on entry and exit to the overrides. Here is the entire class...
using System;
using System.Windows.Controls;
public class TestControl : Decorator
{
protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
{
Console.WriteLine("OnRender Entered");
base.OnRender(drawingContext);
Console.WriteLine("OnRender Exited");
}
protected override void OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo)
{
Console.WriteLine("OnRenderSizeChanged Entered");
base.OnRenderSizeChanged(sizeInfo);
Console.WriteLine("OnRenderSizeChanged Exited");
}
}
And as I feared... here is the output...
OnRender Entered
OnRender Exited
OnRenderSizeChanged Entered
OnRenderSizeChanged Exited
So what am I missing here?
More importantly, how can I get the ActualWidth and ActualHeight values after the layout subsystem has done its job, but before the control is rendered so I can create the geometry before it's needed in the OnRender override?
My latest implementation overrides ArrangeOverride as the value that's passed in there is a size containing what the ActualWidth and ActualHeight values should be after the core layout system takes into consideration HorizontalAlignment and VerticalAlignment with values of 'Stretch', minimums and maximums, etc, but what they actually are depends on the value that's returned from that override so it's a little more complex than that.
Either way, I'm still wondering why the OnRenderSizeChanged call doesn't happen when it's supposed to. Thoughts?
Mark
In general, you should be able to get the correct size from ArrangeOverride. This doesn't include things like Margin, but that probably shouldn't be taken into account. You could either use the size passed as a parameter as your "render" size or use the return value of the base.ArrangeOverride call.
EDIT:
The OnRender method is called from the Arrange method, after OnArrangeOverride is ultimately called. The OnRenderSizeChanged on the other hand is called from UpdateLayout, which is effectively dispatched to be executed all at once for a given section of the visual tree. This is why the OnRenderSizeChanged is called after the OnRender.
The documentation may refer to the "rendering" as in actually rendered to the screen, not when OnRender is called. WPF can cache the rendering instructions for a given element and execute them when needed. So the fact that OnRender is called before OnRenderSizeChanged, doesn't mean it's actual rendering instructions are committed to the screen at that time.
You can modify your OnRenderSizeChanged to force OnRender to be called again using:
protected override void OnRenderSizeChanged(System.Windows.SizeChangedInfo sizeInfo)
{
Console.WriteLine("OnRenderSizeChanged Entered");
base.OnRenderSizeChanged(sizeInfo);
this.InvalidateVisual();
Console.WriteLine("OnRenderSizeChanged Exited");
}
You may also want to skip your OnRender code if RenderSize is "0,0".
In our Silverlight 2 project we have created an attached property to perform on-the-fly translation to text properties of various user controls. To achieve this, we hook the Loaded event of the FrameworkElement when the property is set. When the event fires, we take the existing text property value and perform some simple string substitutions on it, before replacing the property value with the translated text. However, this results in the control being rendered with the untranslated text, then the text is quickly replaced with the translated version.
Is there an alternate event we can hook that would fire before the control is rendered?
I've changed my code so that it now performs the translation as soon as the setter for the attached property is called. There's no need to wait for the FrameworkElement to have finished loading, as I can change the Text property long before the element is rendered.
My initial thoughts on using the Loaded event were to reduce the startup time of the application by only translating the controls that were visible on the screen. As it turns out, I'm duplicating some of the work performed by the runtime, as the runtime won't call the property setter until it needs to anyway.
I'm not totally sure about this, but can you use the LayoutUpdated event. It will fire when the control is resized and such (you could take measures to ensure your code only executes once.)
I know it doesn't seem like the "right" event for this but unfortunately Silverlight kinda leaves you standing there holding it when it comes to events.
I am attempting to create a sukodu (like crossword) player in WPF, and I realize that I have a whole bunch of controls that will need to know the sudoku grid to function.
Because of this, I think the Sudoku Grid object would be a good candidate to create a dependency property. I am about to start the work, but I have some lingering questions:
Who should own the SudokuGrid dependency property? I am thinking the main window UI element should.
Should I set it as a shared dependency property, where all user controls that represent a part of a sudoku grid simply add themselves to the property via .AddOwner() method?
OR
Set it up as an attached property, defined at the main window, and allow child user controls to set up accordingly?
I don't really want child controls to be allowed to set their own grid property value though, so at this time I am leaning towards shared dependency property, but I am not sure it does what I think it does.
Ultimately what I want is one property where if it's set on a parent UI element, all children UI elements that knows about the property will share the same value, overriding any prior value / setting. Does shared dependency do that?
I know it's a bit long winded, but any help would be much appreciated!
I think what you want is an attached property with the Inherits FrameworkPropertyOption. That we every control that wants to know about the grid can just find the grid by getting the value of the attached property (assuming it is set higher up in the tree). This article goes over attached properties and how to set them up.
Alternativly you might like to try out the Model View View-Model (MVVM) pattern and implement the Sudoku grid as a view-model class which each cell being a ceperate view-model class. That way the whole sudoku puzzel is completly seperate from the UI and the UI can just bind to it using appropriate data templates.
For more info on the MVVM pattern se the following:
http://www.codeproject.com/KB/WPF/MVCtoUnitTestinWPF.aspx
http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx