New Posts New Posts RSS Feed: DialogManager stealing focus
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

DialogManager stealing focus

 Post Reply Post Reply
Author
JohnBloom View Drop Down
Groupie
Groupie
Avatar

Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
Post Options Post Options   Quote JohnBloom Quote  Post ReplyReply Direct Link To This Post 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
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post 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>
Back to Top
JohnBloom View Drop Down
Groupie
Groupie
Avatar

Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
Post Options Post Options   Quote JohnBloom Quote  Post ReplyReply Direct Link To This Post 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
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post 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();
        }
    }
Back to Top
JohnBloom View Drop Down
Groupie
Groupie
Avatar

Joined: 30-Nov-2010
Location: Topeka, KS
Posts: 95
Post Options Post Options   Quote JohnBloom Quote  Post ReplyReply Direct Link To This Post 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
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post 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.
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post 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.

        <TextBox TabIndex="0" />
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
    {
    }
}
Back to Top
mgood View Drop Down
IdeaBlade
IdeaBlade
Avatar

Joined: 18-Nov-2010
Location: Emeryville, CA
Posts: 583
Post Options Post Options   Quote mgood Quote  Post ReplyReply Direct Link To This Post 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.
Back to Top
giotis View Drop Down
Groupie
Groupie
Avatar

Joined: 26-Apr-2012
Location: Greece
Posts: 53
Post Options Post Options   Quote giotis Quote  Post ReplyReply Direct Link To This Post 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
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down