Click here to Skip to main content
16,016,022 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have WPF form and say I have a textbox, button X, button Y and couple of hyperlinks. Button x and textbox are initially visible and button Y, hyperlinks are hidden(will be visible when user clicks button X).

When I press tab, focus goes over hidden hyperlink, it won't make them visible though, but still shows a focus on a kind of place holder, which looks bad.

So, basically, I want to disable tabindexing for hidden elements and enable for visible elements

Below is part of my XAML file...

<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>


What I have tried:

1. I tried to set
Focusable="False"
but it doesn't work.

2. Set
KeyboardNavigation.TabNavigation="None"
It works... BUT, it's a static change. I.e. When I make those hyperlink visible, there is no way to tabindex on them. This is because I can't set KeyboardNavigation.TabNavigation=none dynamically.
how can I set KeyboardNavigation.TabNavigation="None" for hidden elements only.

3. Tried to use TabStop, but it's available for Forms and not for Windows
Posted
Updated 14-May-18 9:54am
v4

Your info was very helpful and solved my issue. I had a TextBlock around a Hyperlink control. I was able to add data binding for Visibility and KeyboardNavigation.TabNavigation in the text control and it works great.

Add to xaml resource at top of page.
<!-- Visibility converters for MVVM values -->
<Helpers:BoolToVisibilityConverter x:Key="BoolToVisibility"/>
<Helpers:BoolToTabNavigationConverter x:Key="BoolToTabNavigation"/>

Use converters in TextBlock
<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;
	}
}
 
Share this answer
 
v2
I'm not sure why you would want to do that. Toggling the visibility enables/disables tabstops. You can check it with the following:
XML
<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>
 
Share this answer
 
Comments
sopi9 27-Nov-17 23:51pm    
Hi, In my case toggling visibility odesn't affect tabindex, it still take focus on hidden element.
Graeme_Grant 27-Nov-17 23:59pm    
I don't think that you understand your problem. I also think that you have not tried the solution. The solution above is a test that demonstrates that it does not suffer from the problem that you are describing. Respect the effort that I put in to try and help you with a working solution. Create a new project and try it before you condemn it.
sopi9 28-Nov-17 1:53am    
Hi, Grame. Well thanks for putting effort for me. I have tried your solution and it works. But, I can't use it as I can't create new xmal or can't make drastic changes to the original xaml. That's why I have posted the xaml I'm having trouble with.
Graeme_Grant 28-Nov-17 1:59am    
You have a problem, your UI is bound too tightly to your code.
Graeme_Grant 28-Nov-17 0:57am    
Don't post here, update the question. I still think that you are not reading what I am writing. It is like we are talking in parallel.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900