I'd like to know is there any other option to show current time without using DispatcherTimer?
Unfortunately app need's to run in slow PC's and DispatcherTimer continuously increasing memory usage. I check that in WPF Performance Profiling Tool and that's true - CPU usage with 1sec timespan is ~5-15%.
And becouse im using class to get time value and show that on label, it would be great if method to show could run without xaml-generated controls.
Thanks!
#EDIT:
DispatcherTimer dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 0);
dispatcherTimer.Start();
and when tick:
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
lbl.Content = DateTime.Now.ToString("F");
// lbl is static label which i create once and show i several windows.
}
Your interval is zero, meaning...ouch. Why is it necessary to update the UI more than 10 times a second? No human being will be able to process the changes if they are that frequent. By default WPF only updates the screen 60 times a second, so your interval should be at least 1000/60 = 16.6 ms. However, I'd argue that something as high as 250ms could be good enough.
Related
Is there any way in WPF to determine the optimal UI update rate, so that
No frames are skipped and
UI stays responsible.
It does not make sense to to a lot work to notify the UI that some values have changed when the render process is not able to keep pace. Indeed, I notice that when I try to update too often, the UI gets unresponsive and only a small fraction of the frames are displayed (e.g. InvalidateVisual() is called 10 times, but only one new frame is displayed). Instead, I would prefer that the UI is updated at the native rendering rate.
Up to now, I already tried with a DispatcherTimer, but even if I reduce the Priority to Background, the update method is called more often than the Rendering occurs (frames are skipped) if the update rate is too high. But this rate obviously depends on the Hardware and the number of elements on the screen. If I further reduce the Priority, the timer is not called at all (perhaps as there is a background thread running to update the values).
Alex
I just wrote a quick test to see what the frame rate I'm getting in a test .Net WPF app.
I'm seeing a rate of between 60-63 frames per second, the monitor refresh rate is 60 Hz, so I guess I'm seeing the UI updating at the native rate.
I wrote this using the CompositionTarget.Rendering event and implemented it as a Behavior and attached it to a TextBlock in a very simple MVVM style app:
XAML:
<TextBlock>
<i:Interaction.Behaviors>
<views:FrameRateBehavior />
</i:Interaction.Behaviors>
</TextBlock>
C# Code:
public sealed class FrameRateBehavior : Behavior<TextBlock>
{
private readonly Queue<long> _ticks = new Queue<long>();
public FrameRateBehavior()
{
_ticks = new Queue<long>();
}
protected override void OnAttached()
{
base.OnAttached();
CompositionTarget.Rendering += CalculateFrameRate;
}
protected override void OnDetaching()
{
base.OnDetaching();
CompositionTarget.Rendering -= CalculateFrameRate;
_ticks.Clear();
}
private void CalculateFrameRate(object sender, EventArgs e)
{
var now = DateTime.Now;
var endTime = now.Ticks;
var startTime = now.AddSeconds(-1).Ticks;
while (_ticks.Any())
{
if (_ticks.Peek() < startTime)
{
_ticks.Dequeue();
continue;
}
break;
}
_ticks.Enqueue(endTime);
var count = _ticks.Count;
AssociatedObject.Text = "FPS: " + count;
}
}
Is there any way I can detect a long touch over a TextBlock (or a Label)?
It is possible to do that in an awaitable fashion. Create a timer with specific interval. Start it when user tapped and return the method when timer elapsed. If user release the hand, return the method with false flag.
public static Task<bool> TouchHold(this FrameworkElement element, TimeSpan duration)
{
DispatcherTimer timer = new DispatcherTimer();
TaskCompletionSource<bool> task = new TaskCompletionSource<bool>();
timer.Interval = duration;
MouseButtonEventHandler touchUpHandler = delegate
{
timer.Stop();
if (task.Task.Status == TaskStatus.Running)
{
task.SetResult(false);
}
};
element.PreviewMouseUp += touchUpHandler;
timer.Tick += delegate
{
element.PreviewMouseUp -= touchUpHandler;
timer.Stop();
task.SetResult(true);
};
timer.Start();
return task.Task;
}
For more information, read this post.
As far as I know there is no built in way so you would have to do something like this
• Capture the start time on the TouchDown event of the control
• Compare this to the release time in the TouchUup event
• If the two are different by X then run your long touch code
There might be a few things you have to code around but that is the basic idea
There is an event called TouchAndHoldGesture and PreviewTouchHoldGesture
Long touch, or press and hold as I think it's formally named, can be detected through the right click event.
It may be that, if you are using a Surface Window, that the right click event is disabled.
There is a ContactHoldGesture event on all Surface controls that you can use. But, and I say this as the guy responsible for creating this feature during my time at Microsoft, this event is very poorly designed and should not be used. It doesn't tell you when the system has decided that a finger has moved too much to count as a "hold" and it doesn't give you information needed to draw an animation telling the user that a "hold" is underway. Your much better off doing what #Kevin suggested and building your own implementation.
In Framework 4.0, I have a WinForm that is opened from another form, displays some stuff and a progress bar, and then sits there. I would like to close that "pop up" form after n secods if the user does not close it manually. What's the smartest way to do that?
Thanks.
Start a timer with the desired interval and then when it ticks the first time, close the form.
Something like this
private Timer _timer;
public PopupForm()
{
InitializeComponent();
_timer = new Timer();
_timer.Interval = 5000; // interval in milliseconds here.
_timer.Tick += (s, e) => this.Close();
_timer.Start();
}
Actually the smartest way would probably putting this in its own StartCountdown() method that takes the time as a parameter. Logic like this normally shouldn't be in a constructor strictly speaking...
What's the best way to detect idle state for a silverlight application? I have read quite a few articles on the net by now and usually they are either for wpf/mobile apps etc.
I have created a DispatcherTimer which locks the screen after 5 minutes and it seems that I will have to go to every widget in every screen(my application has around 4-5 screens) and add a mousebuttondown or mouseenter eventhandler to reset this timer. This doesn't seem to be efficient but just adding the handler to the layroot is not helping either.
Any helpful suggestions?
Thanks
You don't need to modify every control. If you add the following code on startup:
Application.Current.RootVisual.MouseMove += new MouseEventHandler(RootVisual_MouseMove);
Application.Current.RootVisual.KeyDown += new KeyEventHandler(RootVisual_KeyDown);
With the following event handlers:
private void RootVisual_KeyDown(object sender, KeyEventArgs e)
{
idle = false;
}
private void RootVisual_MouseMove(object sender, MouseEventArgs e)
{
idle = false;
}
Where idle is the variable you use in your DispatcherTimer Tick event to check if things are happening or not.
As events bubble up the tree this should work for all your controls.
Handled events will not bubble up to root control. Instead you should use the AddHandler method with handledEventsToo = true.
I've seen some examples of code where StoryBoard is used as Timer, such as:
void Update()
{
if (_sb == null)
{
_sb = new Storyboard();
_sb.Completed += _sb_Completed;
_sb.Duration = new Duration(TimeSpan.FromSeconds(1));
}
if (_sb_completed)
{
_sb.Begin();
_sb_completed = false;
}
}
void _sb_Completed(object sender, EventArgs e)
{
PerformUpdate();
_sb_completed = true;
}
Is Storyboard at some point better than Timer? Why do people use it?
P.S. Question is related to Silverlight and/or WPF.
A Storyboard, like a DispatcherTimer, runs on the UI thread. So in either case you will never see a cross thread exception.
You can use a Storyboard over a DispatcherTimer because the Storyboard has a higher priority.
But im not sure about the Timer object itself as I've never really used it in favor of the Storyboard or DispatcherTimer.
Using a Storyboard is different from using a standard System.Threading.Timer. The Storybroad operates on the main thread hence the Completed even can manipulate the UI elements without getting cross thread exceptions. The standard Timer callback doesn't run on the UI thread and will therefore need additional help to manipulate UI elements.
However as Mark points out if all that is really needed is a delay then a DispatcherTimer would be the more intuative choice. The difference with DispatcherTimer is that its designed to invoke its Tick event regularly whereas the Storyboard will only call Completed at most once for each call to Begin. A DispatcherTimer can be used in this way by calling its Stop method in the first Tick event occurance.