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.
Related
I have a WPF Canvas with .NET-4.5.
I added events (which autocreated methods for) MouseLeftButtonDown and MouseDown. Using MessageBox, I have confirmed these methods are called when a user clicks on the canvas, but I can't find a way to get the mouse position from MouseButtonEventArgs.
When I added events (and autocreated methods for) ManipulationStarted and ManipulationStarting those MessageBoxes don't show up.
private void CenterCanvas_ManipulationStarted(object sender, ManipulationStartedEventArgs e)
{
MessageBox.Show("Doesn't show up"); // never shows up
}
private void CenterCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Shows up"); // shows up, but can't seem to get click position
}
In order to get the mouse position from a MouseEventArgs you would have to call the GetPosition method.
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
var pos = e.GetPosition((IInputElement)sender);
System.Diagnostics.Trace.TraceInformation("MouseDown at {0}", pos);
}
For getting manipulation events you need to set IsManipulationEnabled to true. You may want to take a look at the Touch and Manipulation section in the MSDN Input Overview.
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.
In WPF when the MouseMove event is triggered, I want to check if the left mouse key is pressed, if it's pressed I want to do some calculation.
I have tried this:
private void Window_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
Calculate();
}
}
But when I left-click and hold and move the mouse around the screen the Calculate() only gets called one time (i.e when the mouse starts moving), after that no matter where I move the mouse the method does not get called.
I want the Calculate() method to get called repeatedly while the mouse is moving and while the left mouse key is pressed.
A simple test for me shows this working:
private void MouseMoveEvent(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
_vm.MoveCount++;
}
}
A would suspect that your Calculate method is a synchronous method that's causing problems.
Try calling the method like below. This will start the calculate method in a new thread. Then the updating of the text box will happen in the original thread.
private void WindowMouseMoveEvent(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var worker = new BackgroundWorker();
worker.DoWork += Calculate;
worker.RunWorkerCompleted +=
(o, args) => myTextBox.Text = (string)args.Result;
worker.RunWorkerAsync();
}
}
private void Calculate(object sender, DoWorkEventArgs args)
{
//do work
args.Result = "my new value"
}
If you are working with element derived from Panel class, it fires mouse events only when it has Background property set.
I have verified it works. If I keep the mouse button down and move it over the window, the function gets called repeatedly as long as I move mouse over the window. May be your Calculate function takes a lot of time to execute and return back. So it is a long time before it gets called back again. In that case use multiple thread to called Calculate().
To test that this works I added a label to Window and put line label.Content = DateTime.Now.Ticks; instead of the calculate func here. It keeps updating the value.
If applicable, the CRectTracker::Track function will capture the mouse until the user releases the left mouse button.
http://msdn.microsoft.com/en-us/library/ttwy7427.aspx
I'm having problems getting the Silverlight Button Click event to immediately update a control's UI element and then continue doing some other process. For example, update the text of a control and then do some process. I've tried calling the UpdateLayout() method but that doesn't help.
Here is some sample code:
private void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Testing";
textBlock1.UpdateLayout();
UpdateLayout();
Thread.Sleep(2000);
textBlock1.Text = "Done";
}
In that sample, the textBlock1 control will never display the text "Testing".
It's because you've blocked the UI thread with your Sleep statement which means that the text block won't update until after it's completed, but by that time you've set the text to "Done".
This doesn't work. The UI will block when you do not exit the method. This is why in Silverlight you usually do everything asynchronously:
private void button1_Click(object sender, RoutedEventArgs e)
{
textBlock1.Text = "Testing";
var myTask = /* ... */
myTask.Completed += new FancyDelegate(myTask_Completed);
}
private void myTask_Completed(object sender, RoutetEventArgs e)
{
textBlock1.Text = "Done.";
}
If your tasks do not have asynchronous functions, just wrap them. But be reminded, that when you want to change your textBlock1.Text property from another thread, you must invoke it with the Dispatcher.
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.