canvas draw shape on MouseMove lag - wpf

I have very simple scenario: there is a canvas and I need to draw a line on canvas using MouseMove. But when I move the mouse pointer, second line's point (which is set in mouse move) doesn't match current mouse position.
UPD 2:
Delta depends on speed of mouse, if speed is large - delta is large and noticeable(lag). I've noticed that this bug is more visible if you move your mouse not very fast and not very slow.
You can download sample project here.
Something like on the picture when mouse moves fast:
Some source code:
<Window x:Class="WpfApplication32.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Canvas x:Name="MainCanvas"
MouseLeftButtonDown="MainCanvas_OnMouseLeftButtonDown"
MouseMove="MainCanvas_OnMouseMove"
Background="White"
/>
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApplication32
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Line _currentLine;
private bool _isDrawing;
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
MainCanvas.Focus();
}
private void MainCanvas_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (_isDrawing)
{
_currentLine = null;
_isDrawing = false;
return;
}
_isDrawing = true;
_currentLine = new Line(){Stroke = Brushes.Green};
var p = e.GetPosition(MainCanvas);
_currentLine.X1 = p.X;
_currentLine.Y1 = p.Y;
_currentLine.X2 = p.X;
_currentLine.Y2 = p.Y;
MainCanvas.Children.Add(_currentLine);
}
private void MainCanvas_OnMouseMove(object sender, MouseEventArgs e)
{
if (_currentLine == null)
return;
var p = e.GetPosition(MainCanvas);
_currentLine.X2 = p.X;
_currentLine.Y2 = p.Y;
}
}
}
I've tried to use CompositeTarget.Render, also timer to change second point every 20ms but it didn't help.
I have legacy project in which code depends a lot on this approach(canvas mouseMove and shapes). So I need easiest way to eliminate this lag or some ideas about a reason of this bug) Thanks.
UPD:
I've tried to record video with this problem but I'm not good at it. Here is some screen from my recorded to show the problem:
http://prntscr.com/64hueg
UPD 2:
I've tried to use OnRender of Window object to do the same without canvas. I've used DataContext to draw the line - same issue here. DataContext is considered faster than Canvas and Line (Shape). So this is not Canvas issue.
I've also tried to use WritableBitmap to draw the line - no difference.
I thought that there might be a problem with MouseMove event - I read if there is a lot of objects(not my case but still) MouseMove might fire with delays so I used Win32 WM_MOUSEMOVE but it didn't helped as well. In my case delay between MW_MOUSEMOVE and wpf MouseMove event was <1000 ticks.
The only answer I see so far is render delay. I don't know how to improve it because it is wpf internals =(.
By the way Paint.net seems to use wpf and this problem occurs there as well.

This cannot be fixed because this is due to WPF's internal render system. There will always be a lag even if visual tree is simple. Complex visual tree results to more delay. I've spend a lot of time trying solving this.

Try using MouseMove event not on main canvas but on Window itself.
I recently got same problem using MouseMove on Image and it was laggy as hell
Switching to window's event helped me a lot.
<Window x:Name="Window1" x:Class="WpfApp2.MViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MViewer" Height="454.411" Width="730.515" Loaded="Window_Loaded" Closing="Window1_Closing" ContentRendered="Window1_ContentRendered" MouseMove="Window1_MouseMove">
<Grid>
<Image x:Name="Image1" MouseMove="Image1_MouseMove"/>
<Line Name="Line1" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
<Line Name="Line2" Visibility="Visible" Stroke="Red" StrokeThickness="0.75" />
</Grid>
</Window>
and
private void Window1_MouseMove(object sender, MouseEventArgs e)
{
Line1.Visibility = Visibility.Visible;
Line1.X1 = Mouse.GetPosition(this).X;
Line1.X2 = Mouse.GetPosition(this).X;
Line1.Y1 = 0;
Line1.Y2 = Window1.Height;
Line2.Visibility = Visibility.Visible;
Line2.X1 = 0;
Line2.X2 = Window1.Width;
Line2.Y1 = Mouse.GetPosition(this).Y;
Line2.Y2 = Mouse.GetPosition(this).Y;
}

Related

Showing a text indicator before freezing the Silverlight UI thread

At some point in my Silverlight application I need to perform a heavy operation which freezes the UI thread for about 4 seconds. Before actually performing the operation I am trying to display a simple text indicator via a TextBlock control.
StatusTextBlock.Text = "Performing Some Operation...";
System.Threading.Thread.Sleep(4000); // Just as an example
The problem is that the UI thread freezes before the text of the TextBlock control gets updated. How can I get the notification text shown before the operation begins?
Also, taking the heavy operation to a background thread is not an option for me, as it deals with UI objects (it switches the visual root of the application) and should be executed on the UI thread.
My suggestion is to take it off UI thread and use background thread...
StatusTextBox.Text = "Before Sleep";
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
void bw_DoWork(object sender, DoWorkEventArgs e)
{
System.Threading.Thread.Sleep(8000);}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
StatusTextBox.Text = "after Sleep";
}
I found a solution with the help of Jeff Prosise's blog post: http://www.wintellect.com/cs/blogs/jprosise/archive/2008/10/25/cool-silverlight-trick-5.aspx
The idea is to delay the call performing a long running task till a Silverlight UI rendering event fires. For this I used the CompositionTarget.Rendering event. I subscribed to it in the constructor of the user control:
CompositionTarget.Rendering += this.CompositionTargetRendering;
After I update the text of a TextBlock control I set a private flag, which indicates that some processing should be made in the event handler:
StatusTextBlock.Text = "Performing Some Operation...";
this.processRenderingEvent = true;
And here is the code of the handler:
private void CompositionTargetRendering(Object sender, EventArgs e)
{
if (this.processRenderingEvent)
{
if (++this.renderingEventCounter == 2)
{
System.Threading.Thread.Sleep(4000); // Example of long running task
this.processRenderingEvent = false;
}
}
}
An important point to mention here is that I use a private integer field renderingEventCounter to begin the long running task not the first time the event fires, but the second. The reason for this is that the CompositionTarget.Rendering event is fired just before the Silverlight UI rendering engine draws a new frame on the application's display surface, which means that at the first time the event fires the text of the TextBlock control is not yet updated. But it will be updated the second time.
I think you should implement the BackgroundWorker thread is tsiom's answer, but use the Dispatcher.BeginInvoke to operate on the UI objects, here is a MSDN article on how to use the method: http://msdn.microsoft.com/en-us/library/cc190824%28v=vs.95%29.aspx
Also, see another StackOverflow question for a more comprehensive scenario using the Dispatcher: Understanding the Silverlight Dispatcher
I just ran into this situation myself. The problem (I think) is that before the text gets updated you have already begun the intensive operation, so you have to wait.
What you can do is to attach a listened to some method on the textbox that only gets called once the text is updated (textChanged perhaps?) and THEN call your intensive operation.
This seems hackish to me though...
This is ugly but it works. By delaying the initiliazation of the long running operation using a DispatcherTimer we can allow the UI to be updated before the operation is started.
XAML:
<UserControl x:Class="SilverlightApplication13.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="LayoutRoot"
Background="White">
<StackPanel>
<Border x:Name="Brd01"
Visibility="Collapsed"
Background="Red">
<TextBlock VerticalAlignment="Center"
Margin="30">Sleeping for 4 seconds...</TextBlock>
</Border>
<Border x:Name="Brd02"
Visibility="Collapsed"
Background="Lime">
<TextBlock VerticalAlignment="Center"
Margin="30">Done!</TextBlock>
</Border>
<Button Content="Start Operation"
Click="Button_Click_1"></Button>
</StackPanel>
</Grid>
</UserControl>
Code-behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace SilverlightApplication13
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
//Show the "working..." message
Brd01.Visibility = System.Windows.Visibility.Visible;
//Initialize a timer with a delay of 0.1 seconds
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(100);
timer.Tick += Timer_Tick;
timer.Start();
}
private void Timer_Tick(object sender, EventArgs e)
{
//Start the long running operation
Thread.Sleep(4000);
Brd01.Visibility = System.Windows.Visibility.Collapsed;
Brd02.Visibility = System.Windows.Visibility.Visible;
//Kill the timer so it will only run once.
(sender as DispatcherTimer).Stop();
(sender as DispatcherTimer).Tick -= Timer_Tick;
}
}
}

WPF - Maximizing borderless window by taking in account the user taskbar

I am creating a WPF window with a custom chrome, so I setted ResizeMode="NoResize" and WindowStyle="None" to implement my own chrome. However, there is an issue while maximizing the borderless window: it takes the whole screen.
I found the following trick to fix part of the issue:
http://chiafong6799.wordpress.com/2009/02/05/maximizing-a-borderlessno-caption-window/
This successfully restrain the window size to prevent from covering a taskbar. However, if the user have his taskbar positionned at the left or at the top, this won't work, as the window is at position 0,0.
Is there any way to retrieve more accurately the available area, or to query the user taskbar's position so I can position the maximized window accordingly?
I had a quick play around and it seems that setting the Windows Left and Top properties is ignored when setting WindowState.Maximized with a borderless form.
One workaround would be to ignore the WindowState functions and create your own Maximize/Restore functions
Rough example.
public partial class MainWindow : Window
{
private Rect _restoreLocation;
public MainWindow()
{
InitializeComponent();
}
private void MaximizeWindow()
{
_restoreLocation = new Rect { Width = Width, Height = Height, X = Left, Y = Top };
System.Windows.Forms.Screen currentScreen;
currentScreen = System.Windows.Forms.Screen.FromPoint(System.Windows.Forms.Cursor.Position);
Height = currentScreen.WorkingArea.Height;
Width = currentScreen.WorkingArea.Width;
Left = currentScreen.WorkingArea.X;
Top = currentScreen.WorkingArea.Y;
}
private void Restore()
{
Height = _restoreLocation.Height;
Width = _restoreLocation.Width;
Left = _restoreLocation.X;
Top = _restoreLocation.Y;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
MaximizeWindow();
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
Restore();
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DragMove();
}
base.OnMouseMove(e);
}
}
Xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="74.608" Width="171.708" ResizeMode="NoResize" WindowStyle="None">
<Grid>
<Button Content="Max" HorizontalAlignment="Left" Margin="0,29,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
<Button Content="Restore" HorizontalAlignment="Left" Margin="80,29,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_2"/>
</Grid>
</Window>
Obviously you will want to clean this code up, but it seems to work wherever the Taskbar is located, However you may need to add some logic to get the correct Left, Top if the users font DPI is larger than 100%
Another way to do this is by handling the WM_GETMINMAXINFO Win32 message. The code here shows how to do that.
Note that there are a few things that I would do differently, such as returning IntPtr.Zero instead of (System.IntPtr)0 in WindowProc and making MONITOR_DEFAULTTONEAREST a constant. But that's just coding style changes, and doesn't affect the net result.
Also make sure to pay attention to the update where the WindowProc is hooked during the SourceInitialized event instead of OnApplyTemplate. That's the better place to do it. If you're implementing a class derived from Window, then another option is to override OnSourceInitialized to hook the WindowProc instead of attaching to the event. That's what I normally do.

WPF, Displaying Emgu Image, using Binding

I am familiar with basic code to display an Emgu image in a WPF image box, when all the source code is in the MainWindow.xaml.cs code-behind.
However I am trying to place my Emgu-related code, including the "ProcessFrame" event / Queryframe snippet, into a separate class of static methods so that I can reuse them later. I am doing this because while I will want to be able to grab images from the same camera at a later stage, I also want the flexibility to display those images in a different image box. I am having trouble with this step.
If I could bind the Image box dynamically to a property in the static method (and also enable / disable that binding programmatically), I think that would solve my problem. However, there may be some other problem with the approach I am trying to take. Any code / xaml modifications greatly appreciated.
The following code works, but is unsatisfactory because it forces me to bundle ProcessFrame method into the MainWindow code:
XAML (working):
<Window x:Class="EmguWPF_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Height="215" HorizontalAlignment="Left" Margin="62,66,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="224" />
</Grid>
</Window>
MainWindow Code Snippet (working):
//using statements etc
public partial class MainWindow : Window
{
private Image<Bgr, Byte> image;
private Capture capture = null;
private void button1_Click(object sender, RoutedEventArgs e)
{
InitializeCameras();
timer = new DispatcherTimer();
timer.Tick+=new EventHandler(ProcessFrame);
timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer.Start();
}
private void InitializeCameras()
{
if (capture == null)
{
try
{
capture = new Capture(0);
}
catch // etc
}
}
private void ProcessFrame(object sender, EventArgs arg)
{
image = capture.QueryFrame();
image1.Source = BitmapSourceConvert.ToBitmapSource(image);
}
}
public static class BitmapSourceConvert
{
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
public static BitmapSource ToBitmapSource(IImage image)
{
using (System.Drawing.Bitmap source = image.Bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
}
The following code is where I am up to but need help:
XAML (same as before)
<Window x:Class="EmguWPF_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Image Height="215" HorizontalAlignment="Left" Margin="62,66,0,0" Name="image1" Stretch="Fill" VerticalAlignment="Top" Width="224" />
</Grid>
</Window>
ViewModel Snippet (yes - perhaps too ambitious to be experimenting with design patterns):
public ViewModel()
{
CaptureMethods.InitializeCameras();
timer = new DispatcherTimer();
timer.Tick += new EventHandler(CaptureMethods.ProcessFrame);
timer.Interval = new TimeSpan(0, 0, 0, 0, 10);
timer.Start();
}
CaptureMethods class, not working as a separate class in the way I want it to. You will notice I am now defining the capture field in this class, not in the ViewModel class:
class CaptureMethods
{
private static Capture capture = null;
public static void InitializeCameras()
{
if (capture == null)
{
try
{
capture = new Capture(0);
}
catch // etc
}
}
public static void ProcessFrame(object sender, EventArgs arg)
{
image = capture.QueryFrame();
image1.Source = BitmapSourceConvert.ToBitmapSource(image); // this is my problem line
}
}
// BitmapSourceConvert class not repeated here to avoid duplication.
Thanks!
My suggestion is not to use the WPF Image Box, but the Emgu's ImageBox (Emgu.CV.UI.ImageBox). It is a more complete control and it is designed to use with the framework.
The only problem is that type of control only works with Windows Forms, but you can always create a WinForms User Control with a Emgu's Image Box and use it in WPF inside a WindowsFormsHost.
To expand a bit on celsoap7's answer here is what the resulting XAML might look like:
<Window x:Class="WPFEmguCV.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:emui="clr-namespace:Emgu.CV.UI;assembly=Emgu.CV.UI"
Title="MainWindow" Height="521" Width="1274">
<Grid>
<WindowsFormsHost>
<emui:ImageBox x:Name="CapturedImageBox" Width="409" Height="353" />
</WindowsFormsHost>
</Grid>
</Window>
I (and others) found that marshaling the images onto the UI thread takes too much CPU and so you are better off doing as celsoap7 suggests and put an EmguCV ImageBox inside a WPF WindowsFormsHost.
Sadly that may make the kind of MVVM binding you are asking about quite different from the structure you envisage.

Saving FrameworkElement with its DataContext to image file does no succeed

I have a simple UserControl called UserControl1 that contains a TextBlock:
<UserControl x:Class="WpfApplication2.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<TextBlock Text="{Binding}"/>
</Grid>
</UserControl>
I initialized a new instance of it and gave it a DataContext in code. when the window is closing I have to draw this control to an image file.
The UserControl does not render the bounded text in the file that been created.
and this is my code using the usercontrol:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Closing += MainWindow_Closing;
}
void MainWindow_Closing(object sender, CancelEventArgs e)
{
UserControl1 uc = new UserControl1();
uc.DataContext = "hello";
uc.Height = 100;
uc.Width = 100;
uc.Background = Brushes.LightBlue;
DrawToImage(uc);
}
private void DrawToImage(FrameworkElement element)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(element.DesiredSize));
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
120.0, 120.0, PixelFormats.Pbgra32);
bitmap.Render(element);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (Stream s = File.OpenWrite(#"C:\555.png"))
{
encoder.Save(s);
}
}
}
I Hope It's clear enough, any help will be very appreciated.
You just forgot to force a Layout update on your control after manually Measuring/Arrangeing it (which will not be enough to force binding resolving).
A simple call to UpdateLayout makes it work :
private void DrawToImage(FrameworkElement element)
{
element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(element.DesiredSize));
element.UpdateLayout();
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
120.0, 120.0, PixelFormats.Pbgra32);
bitmap.Render(element);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (Stream s = File.OpenWrite(#"C:\555.png"))
{
encoder.Save(s);
}
}
Edit : More on when bindings are resolved : link
Try to call the function SaveImage() on userControl1.Loaded event
If I do this it works, not sure this is what you want though:
<Window x:Class="DrawImage.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:DrawImage="clr-namespace:DrawImage"
Title="MainWindow" Height="350" Width="525">
<Grid>
<DrawImage:UserControl1 x:Name="uc" Visibility="Hidden"/>
</Grid>
</Window>
void MainWindow_Closing(object sender, CancelEventArgs e)
{
uc.DataContext = "hello";
uc.Height = 100;
uc.Width = 100;
uc.Background = Brushes.LightBlue;
uc.Visibility = Visibility.Visible;
DrawToImage(uc);
}
EDIT
I am now able to reproduce the issue. If I set the DataContext in the Window contstructor then it works. If I set it in the Winndow_Closed event I get the exact same result that you get.
I guess there might no workaround since the WPF needs some time to actually render the text on the UI thread. If you render the PNG before the WPF has rendered the text on the UI thread it will not appear on the PNG.
A workaround does not seem to exist since the window will be destroyed when the Closed event handlers has been running. There is no way to block the UI thread on the one hand to prvevent to window from beeing detroyed when you on the other hand want the UI thread to render the control.
I'd suggest to render the image as soon as the control has been rendered and save the image file when the window is closed.
I posted an Article in my Blog (putting in the account the png Transparancy (causes the black background)):
Saving FrameworkElement as Image
FrameworkElement element = myControl.Content;
// you can set the size as you need.
Size theTargetSize = new Size(1500,2000)
element.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));
element.Arrange(new Rect(theTargetSize ));
// to affect the changes in the UI, you must call this method at the end to apply the new changes
element.UpdateLayout();
You can find the full cod in the Blog Post.

focus visual not showing when navigating focus programically

Whenever I try to move focus programmatically the focus visual (the dotted rectangle) does not display.
What can be done to force this visual to display?
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="OnLoaded">
<StackPanel>
<TextBlock x:Name="a" Focusable="True">A</TextBlock>
<TextBlock Focusable="True">B</TextBlock>
<Button Focusable="False" Click="OnClick">Move Focus</Button>
</StackPanel>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Keyboard.Focus(a);
}
private void OnClick(object sender, RoutedEventArgs e)
{
var request = new TraversalRequest(FocusNavigationDirection.Next);
var elementWithFocus = Keyboard.FocusedElement as UIElement;
if (elementWithFocus != null)
elementWithFocus.MoveFocus(request);
}
}
If you look (in reflector/ilspy) at the KeyboardNavigation's ShowFocusVisual you'll find that the framework will only show it if the last input was from the keyboard (or if an internal static property based on the KeyboardCues system parameter info is true). So I don't think there is a good way to do this short of using reflection to temporarily set that property or asynchronously focusing the element and forcing a keyboard action (maybe using the winforms SendKeys or keybd_event api) but I wouldn't recommend either.

Resources