Setting initial control focus in Silverlight

11,389

Solution 1

I whipped up a quick SL3 app and it is difficult to have the initial focus go to the UserControl let alone to a control within the Silverlight control.

However, see if this solution solves this issue for you. You'll have to use a little JavaScript.

Here's the code for reference:

<%@ Page Language="C#" AutoEventWireup="true" %>

<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
    TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;">
<head runat="server">
    <title>Test Page For TextFocusTest</title>
    <script type="text/javascript">
    window.onload = function()
        {
            document.getElementById('Xaml1').focus();
        }
    </script>
</head>
<body style="height:100%;margin:0;">
    <form id="form1" runat="server" style="height:100%;">
        <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
        <div  style="height:100%;">
            <asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/TextFocusTest.xap" Version="2.0" Width="100%" Height="100%" />
        </div>
    </form>
</body>
</html>

Once your SL control has focus, you can further set the focus to a specific control using something like:

namespace SilverlightApplication2
{
    public partial class MainPage : UserControl
    {
        public MainPage ()
        {
            InitializeComponent ();

            this.GotFocus += new RoutedEventHandler (MainPage_GotFocus);
        }

        void MainPage_GotFocus (object sender, RoutedEventArgs e)
        {
            uxLogin.Focus ();
        }
    }
}

where uxLogin is defined in XAML as:

<TextBox x:Name="uxLogin" Height="25" Width="100" />

Solution 2

public MainPage()
{
    InitializeComponent();

    this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    HtmlPage.Plugin.Focus();
    MyTextBox.Focus();
}

Solution 3

If you want to do it in a PRISM or MVVM way (get rid of the code-behind code), you can implement a behavior. In my case I focus the view in the username field if it's empty and in the password if it's set (hence the 2 parameters).

My implementation:

public static class ControlTextFocusBehavior
{
    public static readonly DependencyProperty FocusParameterProperty = DependencyProperty.RegisterAttached(
      "FocusParameter",
      typeof(string),
      typeof(ControlTextFocusBehavior),
      new PropertyMetadata(OnSetFocusParameterCallBack));

    public static readonly DependencyProperty IsEmptyFocusedProperty = DependencyProperty.RegisterAttached(
      "IsEmptyFocused",
      typeof(bool),
      typeof(ControlTextFocusBehavior),
      new PropertyMetadata(true));


    private static void OnSetFocusParameterCallBack(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        Control control = dependencyObject as Control;
        if (control != null)
        {
            control.Loaded += new RoutedEventHandler(control_Loaded);
        }
    }

    private static void control_Loaded(object sender, RoutedEventArgs e)
    {
        Control control = sender as Control;
        control.Loaded -= new RoutedEventHandler(control_Loaded);

        DependencyObject dependencyObject = sender as DependencyObject;
        if (dependencyObject != null)
        {
            bool isEmptyFocused = GetIsEmptyFocused(dependencyObject);
            bool isNullOrEmpty = string.IsNullOrEmpty(GetFocusParameter(dependencyObject));
            if ((isEmptyFocused && isNullOrEmpty) ||
                (!isEmptyFocused && !isNullOrEmpty))
            {
                HtmlPage.Plugin.Focus();
                control.Focus();
            }
        }
    }

    public static void SetFocusParameter(DependencyObject dependencyObject, string parameter)
    {
        dependencyObject.SetValue(FocusParameterProperty, parameter);
    }

    public static string GetFocusParameter(DependencyObject dependencyObject)
    {
        return dependencyObject.GetValue(FocusParameterProperty) as string;
    }


    public static void SetIsEmptyFocused(DependencyObject dependencyObject, bool parameter)
    {
        dependencyObject.SetValue(IsEmptyFocusedProperty, parameter);
    }

    public static bool GetIsEmptyFocused(DependencyObject dependencyObject)
    {
        return (bool)dependencyObject.GetValue(IsEmptyFocusedProperty);
    }
}

Solution 4

If you want this code:

window.onload = function()

    {
        document.getElementById('Xaml1').focus();
    }

work in all browsers, you must set the tabIndex for element with id="Xaml1".

Sorry for my English :)

Share:
11,389
Nick Gotch
Author by

Nick Gotch

I've been a software engineer in a variety of industries over the past 15 years. The majority of that time has been developing business software for academic, financial, healthcare, and management services, primarily in C#.NET (starting with .NET 1.1) and Python, but also with a fair amount of Perl and a mix of other languages (C++, VB.NET, Lua, etc.). I've also spent about 5 years of that time in the mobile games industry, working on the Android release of Fieldrunners and the server backend for Fieldrunners Attack!.

Updated on June 17, 2022

Comments

  • Nick Gotch
    Nick Gotch almost 2 years

    I'm looking for a way to automatically set the initial focus on a Silverlight UserControl to a specific control. I have a login page with a user name textbox and I'd like to have it so that as soon as the user goes to the page their cursor is already positioned and waiting in the username textbox instead of having to make them click the box.

    I tried calling .Focus in the UserControl's Loaded event but with no success. Anyone know how to do this?

  • Nick Gotch
    Nick Gotch almost 15 years
    This solution seems to work in IE but I can't get the Silverlight control to gain focus in Firefox or Chrome.
  • Nick Gotch
    Nick Gotch almost 15 years
    Still can't get this working in other browsers but I'm going with this solution since most of the users will be in IE anyway and the others will just have to click the Silverlight control. Thanks!
  • Scott Marlowe
    Scott Marlowe almost 15 years
    your welcome. I've had a lot of problems with Silverlight and FF--resizing and just getting the control to display. In one case, I finally gave up and have one solution for IE and another for FF. Not the best way, but oh well.