Как установить фокус на кнопку при нажатии на список радиокнопок? - PullRequest
0 голосов
/ 26 апреля 2020

Я новичок в мире WPF, столкнулся с проблемой, когда кнопка теряет фокус при нажатии на другой элемент управления. У меня есть страница xaml со списком переключателей в следующем формате:

User | Account | Preferences

Вот как выглядит мой пользовательский интерфейс user_interface

Все вышеперечисленное радио кнопки используют похожий код и находятся в LaunchUserViewControl.xaml

<RadioButton Name="userRadioButton" GroupName="tabcontrol" FontWeight="Bold" HorizontalAlignment="Stretch" VerticalAlignment="Center" 
AutomationProperties.Name="User"
IsChecked="{Binding IsUserTabSelected, Mode=TwoWay}"
Command="{Binding TabSelectedCommand}" 
CommandParameter="{x:Static ViewModel:LaunchViewTabIndex.UserTab}" 
Style="{DynamicResource TabButtonStyle}" IsTabStop="False"
Focusable="False">
   <TextBlock Text="User" Foreground="{StaticResource userTabTextColor}"/>
</RadioButton>

<RadioButton Name="accountRadioButton" GroupName="tabcontrol" FontWeight="Bold" HorizontalAlignment="Stretch" VerticalAlignment="Center" 
AutomationProperties.Name="Account"
IsChecked="{Binding IsAccountTabSelected, Mode=TwoWay}"
Command="{Binding TabSelectedCommand}" 
CommandParameter="{x:Static ViewModel:LaunchViewTabIndex.AccountTab}" 
Style="{DynamicResource TabButtonStyle}" IsTabStop="False"
Focusable="False">
   <TextBlock Text="Account" Foreground="{StaticResource accountTabTextColor}"/>
</RadioButton>

<ContentControl Grid.Row="1" IsTabStop="False">
    <Grid>
        <ContentControl  x:Name="userTabItemUserControl"  IsTabStop="False" 
            Visibility="{Binding Path=IsUserTabSelected, Converter={StaticResource BoolToVisConverter}}"
            HorizontalAlignment="Stretch"  >
        </ContentControl>
        <ContentControl  x:Name="accountTabItemUserControl"  IsTabStop="False"
            Visibility="{Binding Path=IsAccountTabSelected, Converter={StaticResource BoolToVisConverter}}"
            HorizontalAlignment="Stretch"  >
        </ContentControl>
    </Grid>
</ContentControl>

, когда я нажимаю переключатель пользователя, будет загружен userviewcontrol, и то же самое с учетной записью, accountviewcontrol будет загружен.

Вот пользовательский контроль,

<Button extension:FocusExtension.IsFocused="{Binding IsDefaultTabSelected}" Grid.Row="1" Grid.Column="0" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Transparent"
                AutomationProperties.Name="Profile"
                Command="{Binding UserCommand}" CommandParameter="{x:Static metadata:Type.User}" TabIndex="2"
            >
            <Button.Template>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border x:Name="btnProfileBorder" BorderBrush="LightGray" BorderThickness="1" >
                        <Grid x:Name="grdProfile"  Background="{TemplateBinding Background}" >
                            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                <Label Style="{StaticResource Label_Heading_Blue}" Content="Profile"></Label>
                            </StackPanel>
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="grdProfile" Property="Background" Value="{StaticResource ProfileButtonHighlightColor}"  />
                            <Setter TargetName="btnProfileBorder" Property="BorderBrush" Value="Gray" />

                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                            <Setter TargetName="btnProfileBorder" Property="BorderBrush" Value="red"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button
<Button extension:FocusExtension.IsFocused="{Binding IsDetailsSelected}" Grid.Row="1" Grid.Column="0" Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Transparent"
                AutomationProperties.Name="Details"
                Command="{Binding UserCommand}" CommandParameter="{x:Static metadata:Type.Details}" TabIndex="2"
            >
            <Button.Template>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border x:Name="btnDetailsBorder" BorderBrush="LightGray" BorderThickness="1" >
                        <Grid x:Name="grdDetails"  Background="{TemplateBinding Background}" >
                            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                                <Label Style="{StaticResource Label_Heading_Blue}" Content="Details"></Label>
                            </StackPanel>
                        </Grid>
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="grdDetails" Property="Background" Value="{StaticResource DetailsButtonHighlightColor}"  />
                            <Setter TargetName="btnDetailsBorder" Property="BorderBrush" Value="Gray" />

                        </Trigger>
                        <Trigger Property="IsFocused" Value="True">
                            <Setter Property="FontWeight" Value="Bold" />
                            <Setter TargetName="btnDetailsBorder" Property="BorderBrush" Value="red"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Button.Template>
        </Button

В моем LaunchUserViewControl.xaml.cs я добавил ниже модель

[Dependency]
public ILaunchViewModel ViewModel
{
    get { return (ILaunchViewModel)DataContext; }
    set
    {
        DataContext = value;
        userTabItemUserControl.Content = Load Content from userTabItemUserControl;
    }
}

ВЫПУСК

Когда я нажимаю переключатель пользователя, я должен увидеть загруженный userViewcontrol. Это работает нормально. Когда я нажимаю на кнопку UserButton, я должен видеть выделение фокуса на кнопке, это работает.

Проблема, с которой я сталкиваюсь, заключается в том, что при переходе на вкладку Account я вижу, что кнопка профиля теряет фокус . когда я снова возвращаюсь к экрану, мне нужно установить фокус на кнопку профиля. Я попытался использовать FocusExtension.IsFocussed в этом сообщении , а также добавил Focussable = "false" для переключателя пользователя. Когда я прикрепляю обработчик события Got_focus к кнопке, я вижу, что кнопка получает фокус, но когда я смотрю на пользовательский интерфейс, я не вижу, что фокус выбран. Я использовал Live Visual Tree для проверки свойств кнопки и вижу следующее: enter image description here

Вот код, который я использую для FocusExtension

 public static class FocusExtension
    {
        public static readonly DependencyProperty IsFocusedProperty =
            DependencyProperty.RegisterAttached("IsFocused", typeof(bool?), typeof(FocusExtension), new FrameworkPropertyMetadata(IsFocusedChanged) { BindsTwoWayByDefault = true });

        public static bool? GetIsFocused(DependencyObject element)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            return (bool?)element.GetValue(IsFocusedProperty);
        }

        public static void SetIsFocused(DependencyObject element, bool? value)
        {
            if (element == null)
            {
                throw new ArgumentNullException("element");
            }

            element.SetValue(IsFocusedProperty, value);
        }

        private static void IsFocusedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var fe = (FrameworkElement)d;

            if (e.OldValue == null)
            {
                fe.GotFocus += FrameworkElement_GotFocus;
                fe.LostFocus += FrameworkElement_LostFocus;
            }

            if (!fe.IsVisible)
            {
                fe.IsVisibleChanged += new DependencyPropertyChangedEventHandler(fe_IsVisibleChanged);
            }

            if ((bool)e.NewValue)
            {
                fe.Focus();

            }
        }

        private static void fe_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var fe = (FrameworkElement)sender;
            if (fe.IsVisible && (bool)((FrameworkElement)sender).GetValue(IsFocusedProperty))
            {
                fe.IsVisibleChanged -= fe_IsVisibleChanged;
                fe.Focus();

            }
        }

        private static void FrameworkElement_GotFocus(object sender, RoutedEventArgs e)
        {
            var senderControl = ((FrameworkElement)sender);
            senderControl.SetCurrentValue(IsFocusedProperty, true);

        }

        private static void FrameworkElement_LostFocus(object sender, RoutedEventArgs e)
        {
            var senderControl = ((FrameworkElement)sender);
            senderControl.SetCurrentValue(IsFocusedProperty, false);

        }
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...