silverlight keydown event doesn't work - silverlight

I use VS2010, C# to develop Silverlight 4 app, I use following code in my XAML file:
<Canvas x:Name="Scene" FlowDirection="LeftToRight" Background="White" KeyDown="Scene_KeyDown" MouseMove="Scene_MouseMove">
and this is my XAML.cs file, I want to display a message box if any key is pressed (it is for test only):
private void Scene_KeyDown(object sender, KeyEventArgs e)
{
MessageBox.Show("1");
}
but nothing is displayed after keys are pressed! what is going wrong? should I set any property? command? tabstop? keypreview?
please help me

Looks like this answer will solve your problem:
You need to have at least something inside the Canvas that can receive
focus, and you will find that the event will bubble up.

Related

Search control on WP7/WP7.5

Could anyone tell me which controls are used in WP7 / WP7.5 where we go on e-mails reading, and when we click on the "search" button?
It appears on the top of a searchbox (a TextBox) and the middlle/bottom of the page is a little blurred. I need to code an application like this, and I don"t know which control to use.
Thanks a lot.
Best regards
There's no one control that does the exact scenario you described.
You'll have to add a Textbox and a list for search on the bottom by yourself. Then, respond when the user hits the the "Enter" key, like so:
XAML:
<TextBox Name="textBox1" KeyDown="OnKeyDownHandler"/>
C#:
private void OnKeyDownHandler(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
//Search the data source you want
}
}
You can use a TextBox and a list box to show the searched result. If you want you can use an image button to show search icon. You can use this button's click event to perform the search operation and can show the result in the listbox below.

ComboBox Event not Comming

I am using silverlight. I have problem that added "ComboBox" on simple Silverlight Page. But there is no event for ComboBox.
My guess is that you've added a ComboBox element in XAML, and are looking for a SelectionChanged event in code behind.
If so, try this:
Add the SelectionChanged attribute to your ComboBox like this:
<ComboBox SelectionChanged="ComboBox_SelectionChanged">
</ComboBox>
Then go into your codebehind (F7 if you are in XAML view) and add the following inside your page class:
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
That should get you started. Past that I would take some time to go through a few beginner complete Silverlight tutorials -- this should help familiarize you with both visual studio and the structure of a Silverlgiht app.

WPF WindowsFormsHost does not bubble up untreated key gestures

Ok, I'm not sure I understand how this should work, but in my app I have bound a key gesture (Ctrl+K) to a RoutedCommand. No matter where I focus in my app, the key combination works, except if I use it inside of a WindowsFormsHost containing a web browser control. I tried capturing the PreviewKeyDown event for the web browser control and setting the IsInputKey to false. This should, in theory, cause the Host to consider the key gesture untreated and send it upwards, but that doesn't happen.
UPDATE:
If I override the control's bool IsInputKey (Keys keyData) and return false, it works and the command gets executed as it should.
Maybe there is something wrong in the way I handled PreviewKeyDown?
private void browser_PreviewKeyDown (object sender, PreviewKeyDownEventArgs e)
{
e.IsInputKey = false;
}
I expected this to allow me to capture any key combination from my main window. I'd rather fix this with event handling than extending a control...
If I understand it correctly you want to prevent that the keystroke is handled by the hosted Winform. However, your example code indicates that you try to handle it inside the hosted control.
For handling tunneling events you better handle it "outside" the hosted control, in the WPF visual tree. You can - for example - handle it as follows:
<Grid PreviewKeyDown="Grid_PreviewKeyDown" PreviewMouseDown="Grid_PreviewMouseDown" Height="250" Width="250">
<WindowsFormsHost Name="windowsFormsHost1">
<wf:Form1 TopLevel="False" />
</WindowsFormsHost>
</Grid>
By setting the event as handled as follows, it prevents that the event is propagated further down the visual tree:
private void Grid_PreviewKeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
}

Can't set focus to a child of UserControl

I have a UserControl which contains a TextBox. When my main window loads I want to set the focus to this textbox so I added Focusable="True" GotFocus="UC_GotFocus" to the UserControls definition and FocusManager.FocusedElement="{Binding ElementName=login}" to my main windows definition. In the UC_GotFocus method i simply call .Focus() on the control i want to focus on but this doesn't work.
All i need to do is have a TextBox in a UserControl receive focus when the application starts.
Any help would be appreciated, thanks.
I recently fixed this problem for a login splash screen that is being displayed via a storyboard when the main window is first loaded.
I believe there were two keys to the fix. One was to make the containing element a focus scope. The other was to handle the Storyboard Completed event for the storyboard that was triggered by the window being loaded.
This storyboard makes the username and password canvas visible and then fades into being 100% opaque. The key is that the username control was not visible until the storyboard ran and therefore that control could not get keyboard focus until it was visible. What threw me off for awhile was that it had "focus" (i.e. focus was true, but as it turns out this was only logical focus) and I did not know that WPF had the concept of both logical and keyboard focus until reading Kent Boogaart's answer and looking at Microsoft's WPF link text
Once I did that the solution for my particular problem was straightforward:
1) Make the containing element a focus scope
<Canvas FocusManager.IsFocusScope="True" Visibility="Collapsed">
<TextBox x:Name="m_uxUsername" AcceptsTab="False" AcceptsReturn="False">
</TextBox>
</Canvas>
2) Attach a Completed Event Handler to the Storyboard
<Storyboard x:Key="Splash Screen" Completed="UserNamePassword_Storyboard_Completed">
...
</Storyboard>
and
3) Set my username TextBox to have the keyboard focus in the storyboard completed event handler.
void UserNamePassword_Storyboard_Completed(object sender, EventArgs e)
{
m_uxUsername.Focus();
}
Note that calling item.Focus() results in the call Keyboard.Focus(this), so you don't need to call this explicitly. See this question about the difference between Keyboard.Focus(item) and item.Focus.
Its stupid but it works:
Pop a thread that waits a while then comes back and sets the focus you want. It even works within the context of an element host.
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
System.Threading.ThreadPool.QueueUserWorkItem(
(a) =>
{
System.Threading.Thread.Sleep(100);
someUiElementThatWantsFocus.Dispatcher.Invoke(
new Action(() =>
{
someUiElementThatWantsFocus.Focus();
}));
}
);
}
Just recently I had a list-box that housed some TextBlocks. I wanted to be able to double click on the text block and have it turn into a TextBox, then focus on it and select all the text so the user could just start typing the new name (Akin to Adobe Layers)
Anyway, I was doing this with an event and it just wasn't working. The magic bullet for me here was making sure that I set the event to handled. I figure it was setting focus, but as soon as the event went down the path it was switching the logical focus.
The moral of the story is, make sure you're marking the event as handled, that might be your issue.
“When setting initial focus at application startup, the element to
receive focus must be connected to a PresentationSource and the
element must have Focusable and IsVisible set to true. The recommended
place to set initial focus is in the Loaded event handler"
(MSDN)
Simply add a "Loaded" event handler in the constructor of your Window (or Control), and in that event handler call the Focus() method on the target control.
public MyWindow() {
InitializeComponent();
this.Loaded += new RoutedEventHandler(MyWindow_Loaded);
}
void MyWindow_Loaded(object sender, RoutedEventArgs e) {
textBox.Focus();
}
since i tried a fuzquat's solution and found it the most generic one, i thought i'd share a different version, since some complained about it looking messy. so here it is:
casted.Dispatcher.BeginInvoke(new Action<UIElement>(x =>
{
x.Focus();
}), DispatcherPriority.ApplicationIdle, casted);
no Thread.Sleep, no ThreadPool. Clean enough i hope.
UPDATE:
Since people seem to like pretty code:
public static class WpfExtensions
{
public static void BeginInvoke<T>(this T element, Action<T> action, DispatcherPriority priority = DispatcherPriority.ApplicationIdle) where T : UIElement
{
element.Dispatcher.BeginInvoke(priority, action);
}
}
now you can call it like this:
child.BeginInvoke(d => d.Focus());
WPF supports two different flavors of focus:
Keyboard focus
Logical focus
The FocusedElement property gets or sets logical focus within a focus scope. I suspect your TextBox does have logical focus, but its containing focus scope is not the active focus scope. Ergo, it does not have keyboard focus.
So the question is, do you have multiple focus scopes in your visual tree?
I found a good series of blog posts on WPF focus.
Part 1: It’s Basically Focus
Part 2: Changing WPF focus in code
Part 3: Shifting focus to the first available element in WPF
They are all good to read, but the 3rd part specifically deals with setting focus to a UI element in a UserControl.
Set your user control to Focusable="True" (XAML)
Handle the GotFocus event on your control and call yourTextBox.Focus()
Handle the Loaded event on your window and call yourControl.Focus()
I have a sample app running with this solution as I type. If this does not work for you, there must be something specific to your app or environment that causes the problem. In your original question, I think the binding is causing the problem.
I hope this helps.
After having a 'WPF Initial Focus Nightmare' and based on some answers on stack, the following proved for me to be the best solution.
First, add your App.xaml OnStartup() the followings:
EventManager.RegisterClassHandler(typeof(Window), Window.LoadedEvent,
new RoutedEventHandler(WindowLoaded));
Then add the 'WindowLoaded' event also in App.xaml :
void WindowLoaded(object sender, RoutedEventArgs e)
{
var window = e.Source as Window;
System.Threading.Thread.Sleep(100);
window.Dispatcher.Invoke(
new Action(() =>
{
window.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}));
}
The threading issue must be use as WPF initial focus mostly fails due to some framework race conditions.
I found the following solution best as it is used globally for the whole app.
Hope it helps...
Oran
I converted fuzquat's answer to an extension method. I'm using this instead of Focus() where Focus() did not work.
using System;
using System.Threading;
using System.Windows;
namespace YourProject.Extensions
{
public static class UIElementExtension
{
public static void WaitAndFocus(this UIElement element, int ms = 100)
{
ThreadPool.QueueUserWorkItem(f =>
{
Thread.Sleep(ms);
element.Dispatcher.Invoke(new Action(() =>
{
element.Focus();
}));
});
}
}
}
I've noticed a focus issue specifically related to hosting WPF UserControls within ElementHosts which are contained within a Form that is set as an MDI child via the MdiParent property.
I'm not sure if this is the same issue others are experiencing but you dig into the details by following the link below.
Issue with setting focus within a WPF UserControl hosted within an ElementHost in a WindowsForms child MDI form
I don't like solutions with setting another tab scope for UserControl. In that case, you will have two different carets when navigating by keyboard: on the window and the another - inside user control. My solution is simply to redirect focus from user control to inner child control. Set user control focusable (because by default its false):
<UserControl ..... Focusable="True">
and override focus events handlers in code-behind:
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
MyTextBox.Focus();
}
protected override void OnGotKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
base.OnGotKeyboardFocus(e);
Keyboard.Focus(MyTextBox);
}
What did the trick for me was the FocusManager.FocusedElement attribute. I first tried to set it on the UserControl, but it didn't work.
So I tried putting it on the UserControl's first child instead:
<UserControl x:Class="WpfApplication3.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid FocusManager.FocusedElement="{Binding ElementName=MyTextBox, Mode=OneWay}">
<TextBox x:Name="MyTextBox"/>
</Grid>
... and it worked! :)
I have user control - stack panel with two text boxes.The text boxes were added in contructor, not in the xaml. When i try to focus first text box, nothing happend.
The siggestion with Loaded event fix my problem. Just called control.Focus() in Loaded event and everthing.
Assuming you want to set focus for Username textbox, thus user can type in directly every time it shows up.
In Constructor of your control:
this.Loaded += (sender, e) => Keyboard.Focus(txtUsername);
After trying combinations of the suggestions above, I was able to reliably assign focus to a desired text box on a child UserControl with the following. Basically, give focus to the child control and have the child UserControl give focus to its TextBox. The TextBox's focus statement returned true by itself, however did not yield the desired result until the UserControl was given focus as well. I should also note that the UserControl was unable to request focus for itself and had to be given by the Window.
For brevity I left out registering the Loaded events on the Window and UserControl.
Window
private void OnWindowLoaded(object sender, RoutedEventArgs e)
{
ControlXYZ.Focus();
}
UserControl
private void OnControlLoaded(object sender, RoutedEventArgs e)
{
TextBoxXYZ.Focus();
}
I set it in the PageLoaded() or control loaded, but then I'm calling WCF async service and doing stuff that seems to lose the focus. I have to to set it at the end of all the stuff I do. That's fine and all, but sometimes I make changes to the code and then I forget that I'm also setting the cursor.
I had same problem with setting keyboard focus to canvas in WPF user control.
My solution
In XAML set element to Focusable="True"
In element_mousemove event create simple check:
if(!element.IsKeyBoardFocused)
element.Focus();
In my case it works fine.

How Do I Give a Textbox Focus in Silverlight?

In my Silverlight application, I can't seem to bring focus to a TextBox control. On the recommendation of various posts, I've set the IsTabStop property to True and I'm using TextBox.Focus(). Though the UserControl_Loaded event is firing, the TextBox control isn't getting focus. I've included my very simple code below. What am I missing? Thanks.
Page.xaml
<UserControl x:Class="TextboxFocusTest.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Loaded="UserControl_Loaded"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Width="150" VerticalAlignment="Center">
<TextBox x:Name="RegularTextBox" IsTabStop="True" />
</StackPanel>
</Grid>
</UserControl>
Page.xaml.cs
using System.Windows;
using System.Windows.Controls;
namespace PasswordTextboxTest
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
RegularTextBox.Focus();
}
}
}
I found this on silverlight.net, and was able to get it to work for me by adding a call to System.Windows.Browser.HtmlPage.Plugin.Focus() prior to calling RegularTextBox.Focus():
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Browser.HtmlPage.Plugin.Focus();
RegularTextBox.Focus();
}
Plugin.Focus();
didn't work for me.
Calling
Dispatcher.BeginInvoke(() => { tbNewText.Focus();});
From the Load event worked.
thanks Santiago Palladino Dispatcher worked for me perfectly. What I am doing is:
this.Focus();
then
Dispatcher.BeginInvoke(() => { tbNewText.Focus();});
I solved putting in the control constructor:
this.TargetTextBox.Loaded += (o, e) => { this.TargetTextBox.Focus(); };
Are you sure you're not really getting focus? There's a known bug in Beta 2 where you'll get focus and be able to type but you won't get the caret or the border. The workaround is to call UpdateLayout() on the textbox right before you call Focus().
I would try adding a DispatcherTimer on the UserLoaded event that executes the Focus method a few milliseconds after the whole control has loaded; maybe the problem is there.
I also needed to call
Deployment.Current.Dispatcher.BeginInvoke(() => myTextbox.Focus());
interestingly this call is happening inside an event handler when I mouseclick on a TextBlock, collapse the TextBlock and make the TextBox Visible. If I don't follow it by a dispatcher.BeginInvoke it won't get focus.
-Mike
You code to set the focus is correct since if you add a button that calls the same code it works perfectly:
<StackPanel Width="150" VerticalAlignment="Center">
<TextBox x:Name="RegularTextBox" IsTabStop="True" />
<Button Click="UserControl_Loaded">
<TextBlock Text="Test"/>
</Button>
</StackPanel>
So I'm assuming this is something to do with Focus() requiring some kind of user interaction. I couldn't get it to work with a MouseMove event on the UserControl, but putting a KeyDown event to set the focus works (although the template doesn't update to the focused template).
Width="400" Height="300" Loaded="UserControl_Loaded" KeyDown="UserControl_KeyDown">
Seems like a bug to me....
For out-of-browser apps the System.Windows.Browser.HtmlPage.Plugin.Focus(); doesn't exist.
See my question here for other ideas.
It works for me in SL4 and IE7 and Firefox 3.6.12
Final missing "piece" which made focus to work (for me) was setting .TabIndex property
System.Windows.Browser.HtmlPage.Plugin.Focus();
txtUserName.IsTabStop = true;
txtPassword.IsTabStop = true;
if (txtUserName.Text.Trim().Length != 0)
{
txtPassword.UpdateLayout();
txtPassword.Focus();
txtPassword.TabIndex = 0;
}
else
{
txtUserName.UpdateLayout();
txtUserName.Focus();
txtUserName.TabIndex = 0;
}
My profile is not good enough to comment on #Jim B-G's answer but what worked for me was to add a handler for the Loaded event on the RichTextBox and inside that handler add
System.Windows.Browser.HtmlPage.Plugin.Focus();
<YourTextBox>.UpdateLayout()
<YourTextBox>.Focus();
However, it only worked on IE and FF. To get it work on Chrome and Safari, scroll to the bottom of this
I forgot one thing...I haven't found a way to force focus to your Silverlight application on the page reliably (it will work on some browsers and not on others).
So it may be that the Silverlight app itself doesn't have focus. I usually trick the user into clicking a button or something similar before I start expecting keyboard input to make sure that the silverlight app has focus.
I also ran into this problem, but it had arisen from a different case than what has been answered here already.
If you have a BusyIndicator control being displayed and hidden at all during your view, controls will not get focus if you have lines like
Dispatcher.BeginInvoke(() => { myControl.Focus();});
in the load event.
Instead, you will need to call that line of code after your BusyIndicator display has been set to false.
I have a related question here, as well as a solution for this scenario.
Indeed an annoying beheviour. I found a simple straightforward solution:
(VB code)
Me.Focus()
Me.UpdateLayout()
Me.tbx_user_num.Focus()
Me.tbx_user_num.UpdateLayout()
Each element here is essential, as per my project at least (VB2010 SL4 OutOfBrowser).
Credit to : http://www.dotnetspark.com/kb/1792-set-focus-to-textbox-silverlight-3.aspx
None of the above answers worked for me directly, what i did is that I added this event in in the MainPage() constructor:
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
And handled it as follows:
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
System.Windows.Browser.HtmlPage.Plugin.Focus();
RegularTextBox.Focus();
}
My Silverlight version is 4.

Resources