Storyboard does not start again - wpf

I've got a carousel that works fine on a silverlight app, it comes from this website :
Carousel app
Now i want to convert it into a WPF app. This issue is that the storyboard does not start again when the storyboard.begin() is called in StoryBoard.Completed event
private Storyboard timer;
public override void OnApplyTemplate()
{
this.timer.Completed -= new EventHandler(timer_Completed);
this.timer.Completed += new EventHandler(timer_Completed);
this.timer.Begin();
}
void timer_Completed(object sender, EventArgs e)
{
///Code to animate the carousel
this.timer.Begin();
}
The storyboard is initialized in the OnApplyTemplate, retrieving it by is name defined in xaml
Only one Completed event occurs
Thanks for your help

Did you clip some code out of here? I'd guess it isn't actually getting to the Begin() call at the end of timer_Completed, possibly some exception happening before that.

Related

Is there any way to get MainWindow in custom control without using Application class?

I have one custom control which is placed inside the WPF Window,is there any possibility to get that WPF Window in Custom control and hook some events on that Window? without using Application class(ex Application.Current.Mainwindow)
Ahh... how about the Window.GetWindow method?:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
Window parentWindow = Window.GetWindow(this);
}
Note that it won't work in the constructor, but if you use the Loaded event, it works just fine.

Multiple storyboards in a wpf application

I have three storyboards in a wpf application.
begin is single animation
progress is a repeating animation
end is a single animation too
All storyboards animating the same image, the "progress" storyboard is repeating (while a query in an another thread is running), the "begin" storyboard preceeds it, the "end" animation follows it.
I supposed that this is a simple problem: when the application starts, start the "begin" animation, then in an oncompleted event handler, starts the progress animation, etc.
But it doesnt work: the progress animation is starts, but it appears improperly (strange flashing).
I made a "button1" to analyse this, and i noticed then the same method in the button's onclick eventhandler is works (after the begin storyboard is ended, i pushed it, and the progress storyboard is started and appeared perfectly).
(The FillBehavior of the begin animation is "Stop": the button doesnt worked without this setting, but the eventhandler is remains wrong after setting it)
private void Window_Loaded(object sender, RoutedEventArgs e)
{
begin = (Storyboard)FindResource("startanimation");
progress = (Storyboard)FindResource("progressanimation");
end = (Storyboard)FindResource("stopanimation");
begin.Completed += new EventHandler(begin_Completed);
begin.Begin();
}
void begin_Completed(object sender, EventArgs e)
{
progress.Begin(); //not works
}
private void button1_Click(object sender, RoutedEventArgs e)
{
progress.Begin(); //works
}
Any idea?
Try this:
void begin_Completed(object sender, EventArgs e)
{
this.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
progress.Begin();
}
));
}
Eventually I am forced to make a secondary timer, and start the progress animation in the tick event.. Very ugly, but works.
Any other tips are still welcome.

What event is raised on Grid.Children.Add

In my WPF application, I have a single Main window with a Grid. The Login and Shell are 2 separate UserControls added as children to a grid. I need to find out when the Shell is loaded and start a timer from the Main window.
I just need to know as to what event is raised when a UserControl is added using Grid.Children.Add method, so that I can check if Login is loaded or the Shell and start the timer.
I'm not quite sure what you're trying,
but it sounds like you're looking for the Load event:
UserControl MyControl = new UserControl();
MyControl.Loaded += new RoutedEventHandler(MyControl_Loaded);
public void MyControl_Loaded(object sender, RoutedEventArgs e)
{
if (((UserControl)sender).IsLoaded)
{
..... do something
}
}
Hope it helps

Continuously updating an OpenTK GLControl in WindowsFormsHost in WPF - How?

I have an OpenTK GLControl embedden in a WindowsFormsHost in my WPF application.
I want to continuously update and render it.
In Winforms a solution would be to attach the UpdateAndRender method to the Application.Idle event, but there is no such thing in WPF.
So what would be the best way to do (60FPS) updating of my scene and GLControl ?
You can use a System.Timers.Timer to control how often your render code is called. In your window containing the GLControl-in-WindowsFormsHost, declare a private System.Timers.Timer _timer;, then when you're ready to start the rendering loop, set the timer interval and it's event handler, then start it up, as in the following example:
private void btnLoadModel_Click(object sender, RoutedEventArgs e)
{
LoadModel(); // do whatever you need to do to prepare your scene for rendering
_timer = new System.Timers.Timer(10.0); // in milliseconds - you might have to play with this value to throttle your framerate depending on how involved your update and render code is
_timer.Elapsed += TimerElapsed;
_timer.Start();
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
UpdateModel(); // this is where you'd do whatever you need to do to update your model per frame
// Invalidate will cause the Paint event on your GLControl to fire
_glControl.Invalidate(); // _glControl is obviously a private reference to the GLControl
}
You'll clearly need to add using System.Timers to your usings.
You can use Invalidate() for it. This causes the GLControl to redraw it's content.
If you call it at the end of Paint() you may blocking some UI rendering of the other WPF controls.
WPF provides a per frame render event: CompositionTarget.Rendering. This event is called before WPF wants to render the content. Subscribe from it and call Invalidate:
public YourConstructor()
{
//...
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
_yourControl.Invalidate();
}
You need to unsubscribe if you don't use it anymore (to avoid memory leaks).
Here is a How to: Render on a Per Frame Interval Using CompositionTarget from MSDN.
I use GLControl with that method and it works fine. I did not checked how much FPS I have but it feels smooth.
You may also have a look on this: Why is Frame Rate in WPF Irregular and Not Limited To Monitor Refresh?

Silverlight: MouseLeftButtonDown timer to repeatedly fire an event

I am trying to create a custom scrollbar and am using images as button.
For now a simple
I can handle the MouseLeftButtonDown and Up event just fine but what I'd like to do is while its held down, every so many millisecond trigger an event is fired.
I tried something like this but it isn't quite working. Suggestions?
public delegate void Changed(RangeScrollButtonControl sender, int value);
public event Changed OnChanged;
private System.Threading.Timer Timer;
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
this.Timer = new System.Threading.Timer(Timer_Callback, null, 0, 100);
}
private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.Timer = null;
}
private void Timer_Callback(object sender)
{
if (this.OnChanged != null)
{
this.OnChanged(this, 1);
}
}
The piece of functionality you're looking for is a RepeatButton, this will fire it's Click event repeatedly while the mouse button is held down. You can configure the delay and the interval of the events.
You could then style this button to use the image at Silverlight Show
Hope this helps.
Which piece "isn't quite working" ?
Also, could you restyle or retemplate Silverlght's scrollbar similar to what is seen in this blog post to get what you need?
I would use a Storyboard as a timer. Something like:
Then you can do a MouseSTB.Begin. Once the Storyboard is finished you can catch it in the MouseSTB.Completeed Event. In that event you can do what ever you need to do and then just start it over again. It can easilly be controled by setting some flags on the mouseover, mouseenter and mouseleave events. I use these timers in a lot of place and they work just fine and they do not peg the processor.

Resources