Binding a UserControl to a custom BusyIndicator control

后端 未结 2 1423
野的像风
野的像风 2021-01-25 23:46

I have a requirement to focus on a specific textbox when a new view is loaded.

The solution was to add this line of code to the OnLoaded event for the view:



        
相关标签:
2条回答
  • 2021-01-26 00:34

    Without a BusyIndicator present in the view, the common solution to solve the focus problem is to add the code

    Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
    

    to the Loaded event of the view. This actually works even with the BusyIndicator present; however, the BusyIndicator immediately takes focus away from the rest of the Silverlight controls. The solution is to invoke the Focus() method of the control after the BusyIndicator is not busy.

    I was able to solve it by making a control like this:

    public class EnhancedBusyIndicator : BusyIndicator
    {
        public EnhancedBusyIndicator()
        {
            Loaded += new RoutedEventHandler(EnhancedBusyIndicator_Loaded);
        }
    
        void EnhancedBusyIndicator_Loaded(object sender, RoutedEventArgs e)
        {
            AllowedToFocus = true;
        }
    
        private readonly DependencyProperty AllowedToFocusProperty = DependencyProperty.Register("AllowedToFocus", typeof(bool), typeof(EnhancedBusyIndicator), new PropertyMetadata(true));
    
        public bool AllowedToFocus
        {
            get { return (bool)GetValue(AllowedToFocusProperty); }
            set { SetValue(AllowedToFocusProperty, value); }
        }
    
        public readonly DependencyProperty ControlToFocusOnProperty = DependencyProperty.Register("ControlToFocusOn", typeof(Control), typeof(EnhancedBusyIndicator), null);
    
        public Control ControlToFocusOn
        {
            get { return (Control)GetValue(ControlToFocusOnProperty); }
            set { SetValue(ControlToFocusOnProperty, value); }
        }
    
        protected override void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
        {
            base.OnIsBusyChanged(e);
            if (AllowedToFocus && !IsBusy)
            {
                Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
                AllowedToFocus = false;
            }
        }
    }
    

    To use it, replace the BusyIndicator tags in your xaml with the new EnhancedBusyIndicator and add the appropriate namespace.

    Add a new property, ControlToFocusOn inside the element, and bind it to an existing element in the view that you want focus to be on after the EnhancedBusyIndicator disappears:

    <my:EnhancedBusyIndicator
        ControlToFocusOn="{Binding ElementName=NameTextBox}"
        ...
    >
        ...
    </my:EnhancedBusyIndicator>
    

    In this case, I focused to a textbox called NameTextBox.

    That's it. This control will get focus every time we navigate to the page. While we are on the page, if the EnhancedBusyIndicator becomes busy and not busy agiain, focus will not go to the control; this only happens on initial load.

    If you want to allow the EnhancedBusyIndicator to focus to the ControlToFocusOn another time, add another property, AllowedToFocus:

    <my:EnhancedBusyIndicator
        ControlToFocusOn="{Binding ElementName=NameTextBox}"
        AllowedToFocus="{Binding IsAllowedToFocus}"
        ...
    >
        ...
    </my:EnhancedBusyIndicator>
    

    When AllowedToFocus is set to true, the next time EnhancedBusyIndicator switches from busy to not busy, focus will go to ControlToFocusOn.

    AllowedToFocus can also be set to false when loading the view, to prevent focus from going to a control. If you bind AllowedToFocus to a ViewModel property, you may need to change the BindingMode. By default, it is OneTime.

    0 讨论(0)
  • 2021-01-26 00:38

    @Matt, not sure

    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    

    will work in Silverlight 5, have you tried binding it as a static resource?

    0 讨论(0)
提交回复
热议问题