Я новичок в мире WPF, столкнулся с проблемой, когда кнопка теряет фокус при нажатии на другой элемент управления. У меня есть страница xaml со списком переключателей в следующем формате:
User | Account | Preferences
Вот как выглядит мой пользовательский интерфейс
Все вышеперечисленное радио кнопки используют похожий код и находятся в 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 для проверки свойств кнопки и вижу следующее:
Вот код, который я использую для 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);
}
}