I have various stackpanels/grids that are hidden/shown based on a VM property called "TabIndex". Using a converter and a parameter, the if the TabIndex matches the parameter the visibilty is set to visible else it's collapsed.
My issue is that when using the keyboard to tab through the controls, the tab order goes into the collapsed panel controls before it returns to the to visible panel controls.
Question: Is there anyway to prevent the keyboard from tabbing into the collapsed panels; something like setting up tab groups that can be enabled/disabled?
<StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=0}">
Controls in here...
</StackPanel>
<StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=1}">
Controls in here...
</StackPanel>
<StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=2}">
Controls in here...
</StackPanel>
EDIT - Adding converter code.
BaseConverter
/// <summary>
/// A base value converter that allows direct XAML usage
/// </summary>
/// <typeparam name="T">The type of this value converter</typeparam>
public abstract class BaseValueConverter<T> : MarkupExtension, IValueConverter
where T : class, new()
{
#region Private Variables
/// <summary>
/// A single static instance of this value converter
/// </summary>
private static T Coverter = null;
#endregion
#region Markup Extension Methods
/// <summary>
/// Provides a static instance of the value converter
/// </summary>
/// <param name="serviceProvider">The service provider</param>
/// <returns></returns>
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Coverter ?? (Coverter = new T());
}
#endregion
#region Value Converter Methods
/// <summary>
/// The method to convert on type to another
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public abstract object Convert(object value, Type targetType, object parameter, CultureInfo culture);
/// <summary>
/// The method to convert a value back to it's source type
/// </summary>
/// <param name="value"></param>
/// <param name="targetType"></param>
/// <param name="parameter"></param>
/// <param name="culture"></param>
/// <returns></returns>
public abstract object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
#endregion
}
ValueConverter
/// <summary>
/// A converter that takes in an integer and returns a <see cref="Visibility"/>
/// </summary>
public class IntegerToCollapsedVisibilityValueConverter : BaseValueConverter<IntegerToCollapsedVisibilityValueConverter>
{
public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return int.Parse((string)parameter) == (int)value ? Visibility.Visible : Visibility.Collapsed;
}
public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
I think what you're looking for is IsTabStop. By setting this property to false, you can remove it from the tab list and effectively skip over it. You can look at the Microsoft documentation here: https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.control.istabstop?view=netframework-4.7.2
If you already have some code that is going through and disabling/hiding elements, you could just add a {element}.IsTabStop = true/false in the same place. Here is an example: