sopi9 Ответов: 2

Как отключить tabindex для скрытого элемента в WPF


У меня есть форма WPF, и я говорю, что у меня есть текстовое поле, кнопка X, кнопка Y и пара гиперссылок. Кнопка x и текстовое поле изначально видны, а кнопка Y, гиперссылки скрыты(будут видны, когда пользователь нажмет кнопку X).

Когда я нажимаю tab, фокус переходит на скрытую гиперссылку, хотя она не делает их видимыми, но все равно показывает фокус на своего рода держателе места, что выглядит плохо.

Итак, в принципе, я хочу отключить tabindexing для скрытых элементов и включить для видимых элементов

Ниже приведена часть моего XAML-файла...

<pre><Window x:Class="WPF_TabIndexDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_TabIndexDemo"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Border BorderThickness="0" BorderBrush="#FF999999" Margin="1,1,1,1">
        <Border.Effect>
            <DropShadowEffect Color="#cccccc" Opacity="0.83" Direction="60" BlurRadius="50"/>
        </Border.Effect>
        <Grid Background="White">
            <Grid.RowDefinitions>
                <RowDefinition Height="0*"/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Label x:Name="Label" Content="JioCloud" Grid.RowSpan="2" VerticalAlignment="Top" VerticalContentAlignment="Center" Margin="-1,-1,-1,0" Height="26" Padding="30,0,0,0" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" FontSize="13" FontWeight="Regular">
                <Label.Style>
                    <Style TargetType="{x:Type Label}">
                        <Setter Property="Background">
                            <Setter.Value>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                    <GradientStop Color="#f4f4f4" Offset="0"/>
                                    <GradientStop Color="#d4d1d4" Offset="1"/>
                                </LinearGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Style>
                </Label.Style>
            </Label>
            <Image x:Name="Image" HorizontalAlignment="Left" Height="16" Margin="8,4,0,0" Grid.Row="0" Grid.RowSpan="2" VerticalAlignment="Top" Width="16" RenderTransformOrigin="0.5,-3.286" />
            <Button x:Name="BtnClose"  Command="{Binding CloseWindowCommand}" Width="24" Height="24" Margin="606,-1,-2,416"
                    Grid.Row="0" Grid.RowSpan="2">
                <Image Width="12" Height="12"  Margin="4,6,4,2" />
            </Button>
            <Button x:Name="BtnMinimize"  Command="{Binding MinimizeWindowCommand}" Height="24" Width="24" Margin="584,2,20,413"
                    Grid.Row="0" Grid.RowSpan="2">
                <Image Width="12" Height="12"  Margin="6,9,6,3" />
            </Button>

            <Grid Margin="141,122,136,50" Grid.Row="0" Grid.RowSpan="2" Background="White" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="0*"/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <TextBox HorizontalAlignment="Left" x:Name="TbEmailAddress"  VerticalContentAlignment="Center" VerticalAlignment="Center" Width="350" BorderThickness="0,0,0,2" Margin="0,79,0,162" TextOptions.TextHintingMode="Animated" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Bold" FontSize="15" Grid.ColumnSpan="2" Foreground="Black" Background="White" Height="25" BorderBrush="#FF9B9B9B" >
                    <TextBox.Style>
                        <Style TargetType="{x:Type TextBox}">
                            <Setter Property="BorderBrush" Value="#c41215"/>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ElementName=LbEmailError, Path=Text}" Value="">
                                    <Setter Property="BorderBrush" Value="#7d7d7d" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding ElementName=LbEmailError, Path=Text}" Value="{x:Null}">
                                    <Setter Property="BorderBrush" Value="#7d7d7d" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBox.Style>
                </TextBox>
                <TextBlock x:Name="TbForgotPassword" Background="White" Foreground="#FF9B9B9B" HorizontalAlignment="Left" Height="21" Margin="254,81,-18,164" VerticalAlignment="Center" Width="115" Grid.ColumnSpan="2"
                           Grid.Column="0" Visibility="Hidden">
                    <Hyperlink Foreground="#FF9B9B9B" Background="White" FontSize="13" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" NavigateUri="https://www.jio.com/Jio/portal/forgotPassword" TextDecorations="None">
                        <Run Text="Forgot Password" />
                    </Hyperlink>
                </TextBlock>

                <TextBlock x:Name="TbResendOtp" Background="White" Foreground="#FF9B9B9B" HorizontalAlignment="Left" Height="21" Margin="280,80,-17,165" VerticalAlignment="Center" Width="88" Grid.ColumnSpan="2"
                           Grid.Column="0" Visibility="Hidden" >
                    <Hyperlink Foreground="#FF9B9B9B" Background="White" FontSize="13" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" NavigateUri="https://www.jio.com/Jio/portal/forgotPassword" TextDecorations="None">
                        <Run Text="Resend OTP" />
                        <LineBreak></LineBreak>
                    </Hyperlink>
                </TextBlock>


                <TextBlock x:Name="TbGoBack" Foreground="#FF9B9B9B" HorizontalAlignment="Center" Height="28" Margin="132,199,154,39" VerticalAlignment="Center" Width="65" Grid.ColumnSpan="2"
                           Grid.Column="0" Visibility="Hidden" RenderTransformOrigin="0.658,0.571" KeyboardNavigation.TabNavigation="None">
                    <Hyperlink Foreground="#FF9B9B9B" FontSize="14" FontWeight="ExtraBold" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Bold" NavigateUri="https://www.jio.com/Jio/portal/forgotPassword" >
                        <Run Text="Go Back" />
                    </Hyperlink>
                </TextBlock>
            </Grid>
            

            <Button x:Name="BtnLogin" Cursor="Hand" BorderThickness="50" HorizontalAlignment="Center" Content="LOGIN" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" VerticalAlignment="Center" Width="128" Height="35" Margin="240,264,260,139"
                    Grid.Row="0" Grid.RowSpan="2" IsDefault="true" FontSize="15" Foreground="#FFF9F3F3" Visibility="Hidden">
            </Button>
            <Button x:Name="BtnContinue" Cursor="Hand" BorderThickness="50"  HorizontalAlignment="Center" Content="Continue" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" VerticalAlignment="Center" Width="128" Height="35" Margin="240,272,260,131"
                    Grid.Row="0" Grid.RowSpan="2" IsDefault="true" FontSize="15" Foreground="#FFF9F3F3" Click="BtnContinue_Click">
            </Button>
            <TextBlock Grid.Row="0" Height="25" Grid.RowSpan="2" x:Name="PolicyLabel" Margin="147,414,115,-1" Foreground="Gray">
            <TextBlock Width="305" Height="17" Padding="2" FontSize="9" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" HorizontalAlignment="Center" VerticalAlignment="Center" RenderTransformOrigin="0.544,0.294">By proceeding with login, you agree with
                <Hyperlink x:Name="TermsOfServiceHyperlink" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" FontSize="9" NavigateUri="https://static.jiodrive.com/tos.html" >Terms of service
                <Hyperlink.Style>
                    <Style>
                        <Setter Property="Hyperlink.Foreground" Value="DarkOrange"></Setter>
                        <Style.Triggers>
                            <Trigger Property="Hyperlink.IsMouseOver" Value="True">
                                <Setter Property="Hyperlink.Foreground" Value="#F37F20"></Setter>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Hyperlink.Style></Hyperlink>
                <TextBlock Padding="2" FontSize="9" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" Text="&" VerticalAlignment="Top"/>
                <Hyperlink x:Name="PrivacyPolicyHyperlink" FontFamily="/JioCloud;component/Views/Fonts/#JioType-Light" FontSize="9" NavigateUri="https://static.jiodrive.com/privacypolicy.html">Privacy policy
                <Hyperlink.Style>
                    <Style>
                        <Setter Property="Hyperlink.Foreground" Value="DarkOrange"></Setter>
                        <Style.Triggers>
                            <Trigger Property="Hyperlink.IsMouseOver" Value="True">
                                <Setter Property="Hyperlink.Foreground" Value="#F37F20"></Setter>
                            </Trigger>
                        </Style.Triggers>
                    </Style>
                </Hyperlink.Style></Hyperlink>
            </TextBlock>
        </TextBlock>
</Grid>
    </Border>
</Window>


Что я уже пробовал:

1. Я пытался установить
Focusable="False"
но это не работает.

2. Набор
KeyboardNavigation.TabNavigation="None"
Это работает... НО, это статическое изменение, то есть когда я делаю эти гиперссылки видимыми, нет никакого способа табиндексировать их. Это потому что я не могу установить Клавишная навигация.TabNavigation=нет динамично.
как я могу установить Клавишная навигация.TabNavigation="Нет" только для скрытых элементов.

3. Попытался использовать остановка табуляции, но она доступна для формы, а не для Windows

2 Ответов

Рейтинг:
1

Graeme_Grant

Я не уверен, почему вы хотели бы сделать это. Переключение видимости включает/отключает вкладки. Вы можете проверить это следующим образом:

<Window

    x:Class="Tabbing.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    mc:Ignorable="d"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    Title="MainWindow" WindowStartupLocation="CenterScreen"

    Height="350" Width="525">
    <Window.Resources>
        <Storyboard x:Key="OnChecked">
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="MyButton">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContentControl.Content)" Storyboard.TargetName="toggleButton">
                <DiscreteObjectKeyFrame KeyTime="0" Value="Show"/>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="OnUnchecked">
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="MyButton">
                <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Hidden}"/>
            </ObjectAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(ContentControl.Content)" Storyboard.TargetName="toggleButton">
                <DiscreteObjectKeyFrame KeyTime="0" Value="Show"/>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent="ToggleButton.Checked" SourceName="toggleButton">
            <BeginStoryboard Storyboard="{StaticResource OnChecked}"/>
        </EventTrigger>
        <EventTrigger RoutedEvent="ToggleButton.Unchecked" SourceName="toggleButton">
            <BeginStoryboard Storyboard="{StaticResource OnUnchecked}"/>
        </EventTrigger>
    </Window.Triggers>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.Resources>
            <Style TargetType="{x:Type TextBox}">
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
            </Style>
            <Style TargetType="{x:Type StackPanel}">
                <Setter Property="HorizontalAlignment" Value="Center"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
            </Style>
            <Style TargetType="{x:Type ToggleButton}">
                <Setter Property="Padding" Value="10 5"/>
                <Setter Property="Margin" Value="10"/>
            </Style>
            <Style TargetType="{x:Type Button}">
                <Setter Property="Padding" Value="10 5"/>
                <Setter Property="Margin" Value="10"/>
            </Style>
        </Grid.Resources>

        <TextBox Width="200" />
        <TextBox Width="200" Grid.Row="1"/>
        <TextBox Width="200" Grid.Row="2"/>
        <TextBox Width="200" Grid.Row="3"/>

        <StackPanel Orientation="Horizontal" Grid.Row="4">
            <ToggleButton x:Name="toggleButton" Content="Hide" IsChecked="True"/>
            <Button x:Name="MyButton" Content="HELLO!" Visibility="Visible"/>
        </StackPanel>
    </Grid>
</Window>


sopi9

Привет, в моем случае переключение видимости odesn не влияет на tabindex, он все еще фокусируется на скрытом элементе.

Graeme_Grant

Я не думаю, что ты понимаешь свою проблему. Я также думаю, что вы не пробовали это решение. Приведенное выше решение-это тест, который демонстрирует, что оно не страдает от проблемы, которую вы описываете. Уважайте усилия, которые я приложил, чтобы попытаться помочь вам с рабочим решением. Создайте новый проект и попробуйте его, прежде чем осуждать.

sopi9

Привет, Грэйм. Ну что ж, спасибо, что приложили для меня усилия. Я попробовал ваше решение, и оно работает. Но я не могу использовать его, так как не могу создать новый xmal или внести радикальные изменения в исходный xaml. Вот почему я опубликовал xaml, с которым у меня возникли проблемы.

Graeme_Grant

У вас есть проблема, ваш пользовательский интерфейс слишком тесно связан с вашим кодом.

Graeme_Grant

Не публикуйте здесь, обновите вопрос. Я все еще думаю, что вы не читаете то, что я пишу. Как будто мы говорим параллельно.

sopi9

Обновил вопрос.

Рейтинг:
0

SteveFox

Ваша информация была очень полезна и решила мою проблему. У меня был текстовый блок вокруг элемента управления гиперссылкой. Я смог добавить привязку данных для видимости и навигации по клавиатуре.TabNavigation в текстовом элементе управления, и он отлично работает.

Добавьте к ресурсу xaml в верхней части страницы.

<!-- Visibility converters for MVVM values -->
<Helpers:BoolToVisibilityConverter x:Key="BoolToVisibility"/>
<Helpers:BoolToTabNavigationConverter x:Key="BoolToTabNavigation"/>

Использование конвертеров в текстовом блоке
<TextBlock Visibility="{Binding IsLinkVisible, Converter={StaticResource BoolToVisibility}}" KeyboardNavigation.TabNavigation="{Binding IsLinkVisible, Converter={StaticResource BoolToTabNavigation}}">
	<Hyperlink NavigateUri="{Binding url1}">
		<TextBlock Text="{Binding link1}"/>
	</Hyperlink>
</TextBlock>

Covert bool to KeyboardNavigationMode
// bool to KeyboardNavigationMode converter for MVVM classes
[ValueConversion(typeof(bool), typeof(KeyboardNavigationMode))]
public class BoolToTabNavigationConverter : IValueConverter
{
	enum Parameters
	{
		Normal, Inverted
	}
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		bool tabStop = (bool)value;
		var direction = Parameters.Normal;
		if (parameter != null)
			direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);
		if (direction == Parameters.Inverted)
			tabStop = !tabStop;
		return tabStop ? KeyboardNavigationMode.Local : KeyboardNavigationMode.None;
	}

	public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
	{
		return null;
	}
}