views:

99

answers:

3

What do I need to do to the following code so that the cursor is blinking in the second textbox when the window appears?

XAML:

<Window x:Class="TestFocksdfj.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">
    <StackPanel HorizontalAlignment="Left" Margin="10">
        <ContentControl x:Name="FormArea"/>
    </StackPanel>
</Window>

Code Behind:

using System.Windows;
using System.Windows.Controls;

namespace TestFocksdfj
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            StackPanel sp = new StackPanel();

            for (int i = 0; i < 3; i++)
            {
                TextBox tb = new TextBox();
                tb.Width = 200;
                tb.Margin = new Thickness { Bottom = 3 };
                if (i == 1)
                    tb.Focus();
                sp.Children.Add(tb);
            }

            FormArea.Content = sp;
        }
    }
}
A: 

just found a solution at http://apocryph.org/2006/09/10/wtf_is_wrong_with_wpf_focus that works well in my case, but isn't there a more standard way to do this in WPF without such a hack?

using System.Windows;
using System.Windows.Controls;
using System.Threading;
using System;
using System.Windows.Input;

namespace TestFocksdfj
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            StackPanel sp = new StackPanel();

            for (int i = 0; i < 3; i++)
            {
                TextBox tb = new TextBox();
                tb.Width = 200;
                tb.Margin = new Thickness { Bottom = 3 };
                if (i == 2)
                {
                    FocusHelper.Focus(tb);
                }
                sp.Children.Add(tb);
            }

            FormArea.Content = sp;
        }
    }

    //thanks to: http://apocryph.org/2006/09/10/wtf_is_wrong_with_wpf_focus/
    static class FocusHelper
    {
        private delegate void MethodInvoker();

        public static void Focus(UIElement element)
        {
            ThreadPool.QueueUserWorkItem(delegate(Object foo)
            {
                UIElement elem = (UIElement)foo;
                elem.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
                    (MethodInvoker)delegate()
                    {
                        elem.Focus();
                        Keyboard.Focus(elem);
                    });
            }, element);
        }
    }

}
Edward Tanguay
A: 

You would think that tb.focus would be all that is required. You could try setting the tabindex for the second textbox to 0 and then trying tb.focus. Another alternative is this bit of JavaScript...

private void Set_Focus(string controlname)
{
string strScript;

strScript = "<script language=javascript> document.all('" + controlname + "').focus() </script>";
RegisterStartupScript("focus", strScript);
}
pdavis
+2  A: 

After you've called FormArea.Content = sp;, you can call sp.Children[1].Focus(); to give the seconde Textbox focus.

Like this:

public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            StackPanel sp = new StackPanel();

            for (int i = 0; i < 3; i++)
            {

                TextBox tb = new TextBox();
                tb.Width = 200;
                tb.Margin = new Thickness { Bottom = 3 };
                sp.Children.Add(tb);
            }
            FormArea.Content = sp;
            sp.Children[1].Focus();
        }
    }
Pieter Nijs
Nice, that's it, AFTER FormArea.Content is set, makes sense, thanks.
Edward Tanguay
FYI, the reason this is necessary is that `Focus()` actually sets the `FocusedElement` in the containing focus scope. Before sp is added to FormArea, there **is no** containing focus scope so the focus information is lost.
Ray Burns