This project is read-only.

How to set focus from ViewModel in Silverlight

May 11, 2011 at 4:11 PM

I would like to set focus on a control from viewModel code.  For example, the user clicks Save button. If there is an error on a textBox, I want to set the focus from viewModel code on that textBox. How could I accomplish this with Bxf?

Coordinator
May 16, 2011 at 3:12 PM

That's difficult. WPF has a focus manager concept, but Silverlight does not. Even in WPF, I don't think the focus manager supports any type of data binding, so it can't be driven from the viewmodel.

In at least one app, I created an attached property that could be bound to a viewmodel property. This attached property set focus to the control it was attached to when the viewmodel property changed to a specific value. It was something like this:

<TextBox Text="{...}" SetFocus.Set="{...}" />

I'm not sure that's a great solution, and I don't have the code handy so I can't share it right now. But it did work for my limited scenario (which sounds like your scenario).

Jul 9, 2012 at 4:14 PM

Here is one solution to setting focus on the correct control when the form comes up. 

1. You have to make sure the Silverlight has focus when your application starts (App.xaml.cs) by calling the Focus() of the SilverLight Plugin:

        private void Application_Startup(object sender, StartupEventArgs e)
        {
            System.Windows.Browser.HtmlPage.Plugin.Focus();
            RootVisual = new MainPage();
        }

2. You need to sub-class the ApplicationviewModel of T and and a refresh event and raise it in OnRefreshed:

    public class ApplicationViewModel<T> : ViewModel<T>
    {
        public delegate void RefreshEventHandler(object sender, EventArgs args);
        public event RefreshEventHandler Refreshed;

        protected override void OnRefreshed()
        {
            Shell.Instance.ShowStatus(new Status());
            if (Refreshed != null)
            {
                Refreshed(this, new EventArgs());
            }

            base.OnRefreshed();
        }
    }

 3. You need to install Microsoft Expression SDK and reference Microsoft.Expression.Interactions.dll & System.Windows.Interactivity.dll in your project.

4. You need to create a helper class to set to focus to a control when raised (make sure to add a reference to System.Windows.Interactivity):

    public class SetFocusInvoke : TargetedTriggerAction<Control>
    {
        protected override void Invoke(object parameter)
        {
            if (this.Target != null)
                this.Target.Focus();
        }
    }

5. You need to add the call to the helper in your xaml (add namespace System.Windows.Interactivity to your xaml):

    <TextBox 
        x:Name="RequestTextBox" 
        Grid.Column="2" 
        Grid.Row="1" 
        Margin="5,3" 
        Text="{Binding RequestCreditId, Mode=TwoWay, StringFormat='0;-0;#'}">
        <i:Interaction.Triggers>
            <i:EventTrigger 
                EventName="Refreshed" 
                SourceObject="{Binding Mode=OneWay, Source={StaticResource rootViewModelViewSource}, Path=CurrentItem}">
                <local:SetFocusInvoke TargetName="RequestTextBox" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>

This will aways set the initial focus for your view.  Now whenever you need to set focus to something, just follow the same pattern by creating an event and capturing it in your xaml.