WPF MVVM Предотвращение вкладывания клавиатуры в свернутый элемент управления - PullRequest
0 голосов
/ 31 октября 2018

У меня есть различные стековые панели / сетки, которые скрыты / показаны на основе свойства виртуальной машины под названием "TabIndex". Используя конвертер и параметр, если TabIndex соответствует параметру, visibilty устанавливается на видимое, иначе он свернут.

Моя проблема заключается в том, что при использовании клавиатуры для перемещения по элементам управления порядок вкладок переходит в свернутые элементы управления панели, прежде чем он возвращается к видимым элементам управления панели.

Вопрос: есть ли способ предотвратить вставку клавиатуры в свернутые панели; что-то вроде настройки групп вкладок, которые можно включить / отключить?

<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 голосов
/ 01 ноября 2018

Это на самом деле не ответ, потому что я не отвечаю на вопрос, кроме как сказать, что это не повторяется. Я добавляю это как ответ, потому что он слишком велик, чтобы быть комментарием, и требует форматирования.

Повторяю мой комментарий ранее, если что-то есть Collapsed (или даже Hidden), тогда ни у кого в нем не должно быть возможности получить фокус. Например, создайте новый проект Wpf и поместите его в окно, которое он вам дает:

<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 и обратно. Это не относится к Примеру 2 или Примеру 3.

Далее, если я использую пример кода для конвертера:

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

и если я положу это в конструктор окна:

DataContext = new { TabIndex = 2 };

затем, когда я запускаю его, он показывает только элемент с ConverterParameter = 2, а табуляция не позволяет фокусу перемещаться куда-либо еще. Так что в вашей среде определенно происходит что-то еще, чего я не вижу - вам нужно дать Минимальный, полный и проверяемый пример , чтобы позволить людям продолжить расследование.

Кстати, я хочу упомянуть, что TabIndex - это имя свойства в WPF Control , если вы использовали это имя свойства в своей модели представления, не осознавая этого. Например, может быть, вы случайно привязываетесь к этому, а не к той, что на вашей модели представления.

0 голосов
/ 31 октября 2018

Я думаю, что вы ищете 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;
    }
}
...