WPF MVVM防止键盘跳到折叠控件中

时间:2018-10-31 20:30:05

标签: wpf mvvm keyboard-events tabbing

我有多种基于VM属性“ TabIndex”隐藏/显示的堆栈面板/网格。使用转换器和参数,如果TabIndex与参数匹配,则可见性将设置为可见,否则将被折叠。

我的问题是,使用键盘在控件之间进行制表时,制表符顺序会先进入折叠的面板控件,然后再返回到可见的面板控件。

问题:无论如何,有没有防止键盘跳入折叠的面板的方法;诸如设置可以启用/禁用的标签组之类的东西?

<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  -添加转换器代码。

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();
    }
}

2 个答案:

答案 0 :(得分:0)

我认为您正在寻找的是IsTabStop。 通过将此属性设置为false,可以将其从选项卡列表中删除并有效地跳过它。 您可以在此处查看Microsoft文档:https://docs.microsoft.com/en-us/dotnet/api/system.windows.controls.control.istabstop?view=netframework-4.7.2

如果您已经有一些正在处理和禁用/隐藏元素的代码,则只需在同一位置添加一个{element} .IsTabStop = true / false。 这是一个示例:

void button1_click(object sender, RoutedEventArgs e)
{
    if (true)//some flag for checking if you want to hide/disable it
    {
        panel1.IsTabStop = false;
    }
}

答案 1 :(得分:0)

这并不是真正的答案,因为我没有回答这个问题,除了说这是不可重复的。我将此添加为答案,因为它太大了,无法注释,并且需要设置格式。

请稍候重复我的评论,如果某个内容是Collapsed(甚至是Hidden),那么其中的任何内容都将不可能获得关注。例如,创建一个新的Wpf项目,并将其放入它为您提供的Window中:

<StackPanel>
    <StackPanel>
        <TextBox Text="Example1"/>
    </StackPanel>
    <StackPanel Visibility="Hidden">
        <TextBox Text="Example2"/>
    </StackPanel>
    <StackPanel Visibility="Collapsed">
        <TextBox Text="Example3"/>
    </StackPanel>
    <StackPanel>
        <TextBox Text="Example4"/>
    </StackPanel>
</StackPanel>

现在运行该应用程序并将焦点放在Example1中,然后尝试Tabbing。焦点将从Example1转到Example4,然后再返回。它不会转到Example2或Example3。

如果我将示例代码用于转换器,则进一步说明:

<StackPanel>
    <StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=0}">
        <TextBox Text="Example1"/>
    </StackPanel>
    <StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=1}">
        <TextBox Text="Example2"/>
    </StackPanel>
    <StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=2}">
        <TextBox Text="Example3"/>
    </StackPanel>
    <StackPanel Visibility="{Binding TabIndex, Converter={local:IntegerToCollapsedVisibilityValueConverter}, ConverterParameter=3}">
        <TextBox Text="Example4"/>
    </StackPanel>
</StackPanel>

,如果我将其放入Window的构造函数中:

DataContext = new { TabIndex = 2 };

然后,当我运行它时,它仅显示ConverterParameter = 2的项目,并且制表不让焦点移至其他任何地方。因此,在您的环境中肯定还有其他我没有看到的事情-您需要输入Minimal, Complete and Verifiable Example以便人们进行进一步的调查。

毫无用处,我要提到TabIndex is the name of a property on WPF Control,以防万一您在视图模型上使用该属性名称而没有意识到。例如,也许您不小心绑定了该绑定,而不是绑定到视图模型上的绑定。