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.
Related
I write a very easy UserControl
here the Xaml code
<UserControl x:Name="Test1" x:Class="WpfAppXtesting.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"
xmlns:local="clr-namespace:WpfAppXtesting"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Loaded="Test1_Loaded">
<Grid x:Name="GridRoot" Background="Aqua">
<TextBlock x:Name="status" HorizontalAlignment="Left" Height="137" Margin="100,137,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="483" FontSize="48"/>
</Grid>
and here the code behind
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.GridRoot.DataContext = this;
}
private void UserControl1_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case "Connected":
status.Text = ((App)sender).Connected.ToString() ;
break;
}
}
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
(Application.Current as App).PropertyChanged += UserControl1_PropertyChanged;
}
}
the problem is , when import this control in a Window in same project The design mode gets this error.
NullReferenceException: Object reference not set to an instance of an object.
if I run the project everything was good.
If I commented the line in Loaded method
the control was right shown in design mode.
Any Idea?
thanks
Do not assume that Application.Current is your application at design time. For example, when you are using Expression Blend, Current is Expression Blend. At design time, MainWindow is not your application's main window. Typically operations that cause a user/custome control to fail at design time include the following.
Casting Current to your custom subclass of App.
Casting MainWindow to your custom subclass of Window.
Here are two approaches to writing code for design time. The first approach is to write defensive code by checking the null condition. The second approach is to check whether design mode is active by calling the GetIsInDesignMode method. You can read about GetIsInDesignMode at here.
Solution 1:
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
var app = Application.Current as App;
if( app != null)
{
app.PropertyChanged += UserControl1_PropertyChanged;
}
}
Solution 2 :
private void Test1_Loaded(object sender, RoutedEventArgs e)
{
if (!DesignerProperties.GetIsInDesignMode(this))
{
// Design-mode specific functionality
(Application.Current as App).PropertyChanged += UserControl1_PropertyChanged;
}
}
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.
I'm implementing a simple drag and drop feature in a WPF application. I want this application to run on both desktops with no touch support and also on tablets with only touch support.
Currently I have a MouseMove and TouchMove handler, both implementing the same logic (Starting the DoDragDrop()).
How can I route the input from touch to the mouse handler or visa versa to reduce redundant code? Further how would one route a simple tap to a click event?
I just done a quick test and one way to do this is to create a Global event handler.
Since TouchEventArgs and MouseButtonEventArgs derive from InputEventArgs, your global handler will just implement InputEventArgs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
//private void Button_TouchMove(object sender, TouchEventArgs e)
//{
// TouchEventArgs derives from InputEventArgs
//}
// private void Button_MouseMove(object sender, MouseButtonEventArgs e)
//{
// MouseButtonEventArgs derives from InputEventArgs
//}
private void GlobalHandler(object sender, InputEventArgs e)
{
// This will fire for both TouchEventArgs and MouseButtonEventArgs
// If you need specific information from the event args you can just cast.
// e.g. var args = e as MouseButtonEventArgs;
}
}
Xaml:
<Window x:Class="WpfApplication3.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 >
<Button MouseMove="GlobalHandler" TouchMove="GlobalHandler"/>
</Grid>
</Window>
Hope this helps
Despite some posts on this forum and others i cannot find something that tells me how to set the focus on a TextBox.
I have a userControl with many labels and textBoxes. When the form is loaded I want the a particular textBox to have the focus.
I have set the tabIndex but that didn't seem to work.
Any suggestions?
You can use the FocusManager.FocusedElement attached property for this purpose. Here's a piece of code that set the focus to TxtB by default.
<StackPanel Orientation="Vertical" FocusManager.FocusedElement="{Binding ElementName=TxtB}">
<TextBox x:Name="TxtA" Text="A" />
<TextBox x:Name="TxtB" Text="B" />
</StackPanel>
You can also use TxtB.Focus() in your code-behind if you don't want to do this in XAML.
You can apply this property directly on the TextBox :
<TextBox Text="{Binding MyText}" FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"/>
I am new to using WPF and reading through the above examples I had a similar experience trying set the focus to a textbox using the xaml code examples given, i.e. all the examples above didn't work.
What I found was I had to place the FocusManager.FocusElement in the page element. I assume this would probably work as well if you used a Window as the parent element. Anyway, here is the code that worked for me.
<Page x:Class="NameOfYourClass"
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"
Title="Title"
Height="720"
Width="915"
Background="white"
Loaded="pgLoaded"
FocusManager.FocusedElement="{Binding ElementName=NameOfYourTextBox}">
<!-- Create child elements here. -->
</Page>
I have a TextBox inside a Grid inside a DataTemplate which I want to have keyboard focus when it becomes visible. I also found that
<DataTemplate x:Key="DistanceView" DataType="{x:Type vm:ROI}">
<Grid FocusManager.FocusedElement="{Binding ElementName=tbDistance}">
<TextBox x:Name="tbDistance" Grid.Column="1" Grid.Row="1" VerticalAlignment="Bottom"/>
</Grid>
</DataTemplate>
did not work for me.
However when I call Focus() in the parent ContentControl
private void ContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((sender as ContentControl).IsVisible)
{
(sender as ContentControl).Focus();
}
}
it starts to work and the caret is visible in the TextBox. I think the FocusScope has to be given focus for the FocusManager.FocusedElement property to have any effect.
Jerry
From experimenting around, the xaml solution
FocusManager.FocusedElement="{Binding ElementName=yourElement}"
seems to work best when you place it in the highest element in the window hierarchy (usually Window, or the Grid you place everything else in)
Usage:
local:FocusManager.FocusOnLoad="True"
public class FocusManager
{
public static readonly DependencyProperty FocusOnLoad = DependencyProperty.RegisterAttached(
"FocusOnLoad",
typeof(bool),
typeof(FocusManager),
new UIPropertyMetadata(false, new PropertyChangedCallback(OnValueChanged))
);
private static void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
if (!(sender is Control control))
return;
if ((bool) e.NewValue == false)
return;
control.Loaded += (s, e) => control.Focus();
}
public static bool GetFocusOnLoad(DependencyObject d) => (bool) d.GetValue(FocusOnLoad);
public static void SetFocusOnLoad(DependencyObject d, bool value) => d.SetValue(FocusOnLoad, value);
}
FocusManager was not in intellisense and this confused me a bit. I just typed the entire attribute and it worked.
FocusManager.FocusedElement="{Binding ElementName=MyTextBox}"
Microsoft Visual Studio Enterprise 2015 version 14.0.23107.0/C#/WPF
For completeness, there is also a way to handle this from code behind (e.g. in the case of controls that, for whatever reason, are created dynamically and don't exist in XAML). Attach a handler to the window's Loaded event and then use the ".Focus()" method of the control you want. Bare-bones example below.
public class MyWindow
{
private VisualCollection controls;
private TextBox textBox;
// constructor
public MyWindow()
{
controls = new VisualCollection(this);
textBox = new TextBox();
controls.Add(textBox);
Loaded += window_Loaded;
}
private void window_Loaded(object sender, RoutedEventArgs e)
{
textBox.Focus();
}
}
bind the element you want to point the focus in as
FocusManager.FocusedElement= "{Binding ElementName= Comobox1}"
in grid or groupbox etc
Further to my comment on Feb 04 '22, I solved it this way:
In the UserControl definitionin the XAML add a Loaded event handler. (pressing tab after Loaded= will automatically add an event handler to the code behind)
Then edit the event handler in the code behind:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
expressionTextBox.Focus();
}
I'm hoping that WPF is clever enough to handle th unhooking of the evnt at some point, allowing the class to be garbage collected and not give rise to memory leaks, but I don't know. I'd be interested in any comments on that.
Is there a way using WPF to get a video element to start playing when a user puts there mouse pointer over the element? I am wanting to make an interactive digital resource and want a clip of the movie to play when the mouse over the element to click to take them to the movie section. Any help would be great.
This is going to all be contained in a windows application.
If you're using a MediaElement to play your video, just listen for the MouseEntered Event and call Play().
Note: The LoadedBehavior property of MediaElement must be set to Manual in order to be able to interactively stop, pause, and play the media.
Here's an example:
In C# code-behind:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void mediaElement1_MouseEnter(object sender, MouseEventArgs e)
{
mediaElement1.Play();
}
private void mediaElement1_MouseLeave(object sender, MouseEventArgs e)
{
mediaElement1.Stop();
}
private void mediaElement1_Loaded(object sender, RoutedEventArgs e)
{
mediaElement1.Pause();
}
}
In XAML:
<Window x:Class="VideoTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<MediaElement Margin="12"
Name="mediaElement1"
Source="mediaFile.avi"
LoadedBehavior="Manual"
MouseEnter="mediaElement1_MouseEnter"
MouseLeave="mediaElement1_MouseLeave"
Loaded="mediaElement1_Loaded"
/>
</Grid>
</Window>
Found an issue with the
<MediaElement Margin="12"
Name="mediaElement1"
Source="mediaFile.avi"
LoadedBehavior="Manual"
MouseEnter="mediaElement1_MouseEnter"
MouseLeave="mediaElement1_MouseLeave"
Loaded="mediaElement1_Loaded"
/>
It doesnt seem to like the
Loaded="mediaElement1_Loaded"
So I changed my Initialize in my code behind to contain the
mediaElement1.Pause();
And it is working just fine.