Author |
Share Topic Topic Search Topic Options
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Topic: DialogManager stealing focus Posted: 19-Apr-2012 at 12:06pm |
We have written our own behavior that sets the focus to a specific control on the screen. We have some dialogs that start with the focus on a specific control. When the dialog pops up ee see the focus in our control for a split second and then the childwindow steals it. It takes 3 tabs to get back to our control. Any idea about what is going on?
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 19-Apr-2012 at 12:31pm |
Yes, that's an annoying problem. The culprits are the ContentControl and ItemControl. They are tab stops by default and steal the focus. No idea why anybody throught making them tab stops was a good idea. You can easily fix it for your entire application if you add the following two implicit styles to your app. The ContentControl style as seen below also fixes the sizing problem in Silverlight. You can see these in use in TempHire. <Style TargetType="ContentControl">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
<Style TargetType="ItemsControl">
<Setter Property="IsTabStop" Value="False" />
</Style>
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 19-Apr-2012 at 2:09pm |
Thanks, those worked. Now I am only one tab stop away. Our control is getting focus and then the ok button is taking it. I think that most cases focus on the button would be preferred but in this case we want the focus to be in our control ready for user input. How can we keep the button from stealing focus away from our control?
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 19-Apr-2012 at 2:30pm |
Don't know how you implemented your behavior. Have you tried the InitialFocusBehavior from TempHire? I'm doing the same thing as you are describing and it works in my case. [TypeConstraint(typeof(Control))]
public class InitialFocusBehavior : Behavior<Control>
{
protected override void OnAttached()
{
base.OnAttached();
#if SILVERLIGHT
if (!Application.Current.IsRunningOutOfBrowser)
HtmlPage.Plugin.Focus();
#endif
AssociatedObject.Loaded += (sender, args) => AssociatedObject.Focus();
}
}
|
|
JohnBloom
Groupie
Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
|
Post Options
Quote Reply
Posted: 20-Apr-2012 at 7:04am |
Ok I am able to repo this in TempHire now. In the Styles.xaml file you have the buttons set to IsTabStop = false: <Style TargetType="Button">
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="FontSize" Value="10.667" />
<Setter Property="Background" Value="#FFFF0000" />
<Setter Property="Foreground" Value="#FFFFFFFF" />
<Setter Property="Padding" Value="3" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="IsTabStop" Value="False" />
If you remove the setter property you can see the button steal focus. We have a few places where we rely on the buttons being tab stops so we cant turn them all off like that. Any suggestions?
|
-John Bloom
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 20-Apr-2012 at 12:23pm |
Nice find. I had somebody else do the styles for me. I didn't realize he turned of the tab stop for the buttons. When I was implementing the behavior for TempHire I was finding numerous posts from people struggling with this. I thought I had it nailed, but apparently not. I'm not sure how to make this work based on these findings. I saw a suggestion from somebody to use a delay before assigning focus. So, in the Loaded event instead of calling SetFocus right away, start a timer and then set the focus to essentially steal it back from the button. Don't realy like that approach, but don't have anything better at the moment. I'll play around with it when I get a chance to see if I can do anything in the DialogManager.
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 23-Apr-2012 at 5:37pm |
John, I looked into it some more and apparently we've both been over-engineering this. To set the initial focus you don't need a behavior. You simply set TabIndex="0" as in the following example.
The missing link in Cocktail is to set TabIndex="0" on the ContentControl in the dialog host. I will change this for the next release, but you don't have to wait for it. Cocktail actually allows you to replace the out-of-the-box dialog host with your own.
To do this, add a ChildWindow to your solution and replace the XAML with the following. This is the exact same XAML taken from Cocktail except for TabIndex="0" on the ContentControl. Make sure you replace the x:Class with whatever you want to call it.
<controls:ChildWindow x:Class="MyApp.CustomDialogHostView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="277"
d:DesignWidth="800"
HasCloseButton="False"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot"
MinWidth="166"
Margin="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ItemsControl x:Name="DialogButtons" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="75"
Height="23"
Margin="5"
cal:Message.Attach="Close($dataContext)"
Content="{Binding Content}"
IsEnabled="{Binding Enabled}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ContentControl x:Name="ActiveItem"
Width="Auto"
Height="Auto"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
TabIndex="0" />
</Grid>
</controls:ChildWindow> Now, all you have to do is create a corresponding ViewModel that extends from DialogHostBase. Cocktail will discover your custom ViewModel and through the normal Caliburn.Micro convention it will find your custom view.
namespace MyApp
{
public class CustomDialogHostViewModel : DialogHostBase
{
}
}
|
|
mgood
IdeaBlade
Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
|
Post Options
Quote Reply
Posted: 23-Apr-2012 at 5:43pm |
Just to be clear, you still need to keep the styles for the ContentControl and ItemsControl, otherwise the ContentControl will actually get the initial focus. You can also set IsTabStop to false in your custom view, which is what I'm going to add to the out-of-the-box view in Cocktail.
|
|
giotis
Groupie
Joined: 26-Apr-2012
Location: Greece
Posts: 53
|
Post Options
Quote Reply
Posted: 25-Feb-2013 at 8:58am |
Reading the above I want to add a strange behavior of GridView in StaffingResourceSearchView when clicked (left button of mouse) two times in same line loosing the focus. I tried to find the error without success, why happen this?(wpf ver)
Edited by giotis - 25-Feb-2013 at 8:59am
|
|