Problem with WPF graph control - wpf

I've developed a graph control in GDI+ and used a timer in it.. now i'm converting it to
WPF. but when i went on and search for a timer there is no timers in WPF... how can i resolve this problem?any alternative to use?
regards,
rangana.

You can use System.Threading.Timer without any problems I suppose.
Here is an example of a timer which executes every 1 sec:
using System.Threading;
...
TimerCallback timerCallBack = OnTimerCallback;
Timer timer = new Timer(timerCallBack, null, 0, 1000);
...
private void OnTimerCallback(object state)
{
...
}
If you want to update any UI related elements from the timer, you will have to use Dispatcher.BeginInvoke because the timer runs in it's own thread and the UI is owned by the main thread which starts the timer. Here is an example:
private void OnTimerCallback(object state)
{
Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Normal,
(ThreadStart) (() => Background = Brushes.Black));
}

The timer you are looking for is DispatcherTimer http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatchertimer.aspx
But, if you plan to use a timer to drive animations, there are better ways to do that in WPF (just Google WPF animation).

Related

Song class not working properly

In my silverlight WP7 app, I am using XNA library to play sound. Following is the code.
Microsoft.Xna.Framework.Media.Song s = Microsoft.Xna.Framework.Media.Song.FromUri("song", new Uri("bmusic.mp3", UriKind.Relative));
Microsoft.Xna.Framework.FrameworkDispatcher.Update();
Microsoft.Xna.Framework.Media.MediaPlayer.IsRepeating = true;
Microsoft.Xna.Framework.Media.MediaPlayer.Play(s);
It starts playing the sound and stops after a second, while the song is 10 secs long. What is wrong ?
Silverlight is event based, whereas XNA is more loop based. You need to enable XNA framework events, as explained here. As a quick test to see if that is the issue, in your page's constructor, you can add this:
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(30);
timer.Tick += delegate { try { FrameworkDispatcher.Update(); } catch { } };
timer.Start();

How to implement a background worker thread queue

I'm trying to implement my first application using the MVVM pattern. I've manged to get most things working, but now I'm facing a problem with the following (IMHO pretty common) scenario:
Pressing a Button (View) shall invoke a Method (Model). Using a ICommand (ViewModel) this is pretty easy. But what to do if a time consuming operation has to be executed?
My current solution required me to implement a WorkQueue class containing WorkQueueItems. The WorkQueue has a Thread associated with it which executes the WorkQueueItems. Each WorkQueueItem has a Name, a Status and a Progress which is updated during execution.
Each Window has its own WorkQueue - visualized as StatusBar.
My problem: How can a ViewModel find the appropriate WorkQueue? Do I have to pass the WorkQueue to each ViewModel I create (this would be really be annoying)? Or are there other mechanism I could use?
I'm not really familiar with RoutedCommands - tough the basic concept seems to go into this direction. What'd love to see is a solution where I can bind a WorkQueueItem to a Command/Event which then bubbles up to the containing Window where it is added to the Window's WorkQueue.
I also considered making WorkQueue a Singleton - but this only works if I only have one Window at a time.
With the later .Net Frameworks (4.0+) and WPF you can utilize the System.Threading.Tasks library to provide a lot of this work under the hood.
If say your Command on your needs to update a property on your View Model, but it has to wait for the information, you simply start a task to perform the IO:
this.FindDataCommand = new RelayCommand<string>(
/* ICommand.Execute */
value =>
{
Task.Factory
.StartNew<IEnumerable<Foo>>(() => FindData(value))
.ContinueWith(
task =>
{
this.foundData.Clear();
this.foundData.AddRange(task.Result);
},
TaskScheduler.FromCurrentSynchronizationContext());
},
/* ICommand.CanExecute */
value => !String.IsNullOrWhitespace(value));
Breaking this down into manageable parts, we're starting a new task which calls some method IEnumerable<Foo> FindData(string). This is the plain old boring synchronous code you've always written. Likely it already exists on your view model!
Next we tell the framework to start a new task when that one finishes using ContinueWith, but to do it on the WPF Dispatcher instead. This allows you to avoid the hassles of cross-thread problems with UI elements.
You can extend this for monitoring with a helper class:
public class TaskManager
{
private static ConcurrentDictionary<Dispatcher, TaskManager> _map
= new ConcurrentDictionary<Dispatcher, TaskManager>();
public ObservableCollection<WorkItem> Running
{
get;
private set;
}
public TaskManager()
{
this.Running = new ObservableCollection<WorkItem>();
}
public static TaskManager Get(Dispatcher dispatcher)
{
return _map.GetOrAdd(dispatcher, new TaskManager());
}
// ...
Using this class in XAML would be along the lines of adding its instance to your Window's ViewModel:
public TaskManager CurrentTaskManager
{
get { return TaskManager.Get(Dispatcher.CurrentDispatcher); }
}
// <StatusBarItem Content="{Binding CurrentTaskManager.Running.Count}" />
You would then add a method to your TaskManager to handle the adding of tasks to and from the Running collection:
public Task<TResult> StartNew<TResult>(Func<TResult> work)
{
var task = Task.Factory
.StartNew<TResult>(work);
// build our view model
var workItem = new WorkItem(task);
this.Running.Add(workItem);
// Pass the result back using ContinueWith
return task.ContinueWith(
t => { this.Running.Remove(workItem); return t.Result; },
TaskScheduler.FromCurrentSynchronizationContext());
}
Now we simply change our FindDataCommand implementation:
TaskManager.Get(Dispatcher.CurrentDispatcher)
.StartNew<IEnumerable<Foo>>(() => FindData(value))
.ContinueWith(
task =>
{
this.foundData.Clear();
this.foundData.AddRange(task.Result);
},
TaskScheduler.FromCurrentSynchronizationContext());
The WorkItem class could expose the properties on the Task class to the UI, or it could be extended to encapsulate a CancellationToken to support cancellation in the future.
I'm not sure I got the question right, but I feel that using buil in Dispatcher would solve your problem and you do not need implementing WorkQueue manually since Dispatcher implements such a queue for you and able dispatching "worker items" to the UI/any thred using predefined set of priorities. You can execute an operation either synchronously or asynchronously using Dispatcher.Invoke() or Dispatcher.BeginInvoke()
Useful links:
MSDN Magazine: WPF Threads, Build More Responsive Apps With The Dispatcher

Idle time using DispatcherTimer - Not Working

I have an application all done in WPF, using MvvM/Prism/Unity and Remote as datasource.
I need a basic thing that on win forms is really easy, just check if the app is iddle after few minutes , and if is idle, lock the app and show the login screen.
After some search on google I ´ve found one solution that uses DllImport and another using pure Wpf methods.
I don´t know I , after I implemented the Wpf way (pls check the code below) it only works after I login into the app , if I open and click in a simple texbox or hit a search, the idle method is not fired, looks like there is something hanged in the background that makes Wpf idle routine to think that it´s doing something when it´s not.
How can I check all the services/methods/etc.. that are in memory related to may app ? callstack doesn´t show to much for me. I am affraid that or I am not calling in the correct way the remote services or I implemented something wrong on the props PropChanged events/observablecollections/etc...
Is there a better way to do this using 100% Wpf structure ?
private void CheckIdleTime()
{
handler = delegate
{
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(5);
timer.Tick += delegate
{
if (timer != null)
{
timer.Stop();
timer = null;
System.Windows.Interop.ComponentDispatcher.ThreadIdle -= handler;
Console.WriteLine("IDLE! Lets logoff!");
this.LockApplication();
Console.WriteLine("logoff fired");
System.Windows.Interop.ComponentDispatcher.ThreadIdle += handler;
}
};
timer.Start();
Dispatcher.CurrentDispatcher.Hooks.OperationPosted += delegate
{
if (timer != null)
{
timer.Stop();
timer = null;
}
};
};
ComponentDispatcher.ThreadIdle += handler;
}
There will be default window events find the idle time... i think it will be wise if we use same events for wpf or any other applications...
following link will help you to implement it..
Application.Idle event not firing in WPF application

Force redraw before long running operations

When you have a button, and do something like:
Private Function Button_OnClick
Button.Enabled = False
[LONG OPERATION]
End Function
Then the button will not be grayed, because the long operation prevents the UI thread from repainting the control. I know the right design is to start a background thread / dispatcher, but sometimes that's too much hassle for a simple operation.
So how do I force the button to redraw in disabled state? I tried .UpdateLayout() on the Button, but it didn't have any effects. I also tried System.Windows.Forms.DoEvents() which normally works when using WinForms, but it also had no effect.
The following code will do what you're looking for. However I would not use it. Use the BackgroundWorker class for long time operations. It's easy to use and very stable.
Here the code:
public static void ProcessUITasks() {
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(object parameter) {
frame.Continue = false;
return null;
}), null);
Dispatcher.PushFrame(frame);
}
Here you will find a sample on how to use the BackgroundWorker.
InvalidateVisual(); #HCL is right... don't do this
Like you say, it is better to start use a background thread / dispatcher and keep the UI thread unblocked. Consider looking at the Reactive Extensions library from Microsoft for high level asynchronous ui programming
In Windows.Forms, you can Button.Refresh().
In Windows.Forms or WPF, you can yield to the message pump to let it redraw. Async/Await were designed to allow you to do this without the nastiness of HCL's answer.
Private Async Function Button_OnClick
Button.Enabled = False
Await Task.Yield
[LONG OPERATION]
End Function

How to delay window closing in WPF

I try to delay close a window in my App.xaml.ca :
Window splash = new Window();
splash.Show();
Timer timer = new Timer(callback, null, 2000, Timeout.Infinite);
private void callback(object stateInfo)
{
splash.Close();
}
It works fine, but the whole App is shutdowning. What am doing wrong here ?
Be sure to check that you timer callback is coming back on the main dispatcher thread. If not then you will likely be getting an exception when you try to close your window from a different thread.
Use splash.Dispatcher.CheckAccess() to make sure you are on the right thread and if not then use splash.Dispatcher.BeginInvoke((Action) () => splash.Close() to dispatch the call onto the main thread.
Check out this page for more
Here is my solution to this exact same problem:
private async void CloseWindow()
{
await ClosingTasks();
}
private async Task ClosingTasks()
{
await Task.Delay(2000);
this.Close();
}
Where you simply call CloseWindow() when you want to close the current window after the given delay of 2000 mS.
There are different shutdown modes, if that window is closed and it is the last then the application will shut down by default. So you can either see to it that there is still some window around or you can change the shutdown behaviour by setting the ShutdownMode to something that suits your needs.
e.g.
Application.Current.ShutdownMode = System.Windows.ShutdownMode.OnExplicitShutdown;

Resources