Поддержание порядка вкладок, когда элементы управления отключены и включены снова в непредсказуемое время - PullRequest
12 голосов
/ 15 июня 2011

Итак, позвольте мне предупредить вас; Я прошу способ заставить полный хак работать несколько лучше. Я признаю, что это взлом, и я, безусловно, открыт для разных взглядов на проблему в целом. Тем не менее, мне нужно скоро это сделать, если я хочу сделать обрезку кода, и у нас довольно агрессивная дата выпуска.

Таким образом, я не смогу сразу же внести большие изменения, но я могу легко сделать это для первого патча к этому программному обеспечению. Поэтому приветствуются краткосрочные и долгосрочные решения, но предпочтительнее краткосрочное решение (если возможно).

Хорошо, вот в чем проблема; У меня есть приложение, которое отправляет команды на аппаратное устройство робота. После отправки команды, которая требует ожидания (например, физического движения, которое занимает неизвестное количество времени), пользовательский интерфейс переходит в «состояние занятости». Когда это происходит, все элементы управления, которые будут выдавать другую команду блокировки, отключаются, поскольку машина не может их обработать.

Когда пользовательский интерфейс выходит из состояния занятости, все элементы управления снова включаются, но порядок перехода по понятным причинам не поддерживается. Это делает невозможным переход по областям ввода и, поскольку я использую клавиатуру почти исключительно, неприемлемо. Моя текущая схема «решить» эту проблему заключается в следующем:

  1. При запуске зарегистрируйтесь в событии GotFocus для каждого интересующего элемента управления в приложении. Это затрудняется тем, что это приложение WPF MVVM, а также тем, что некоторые элементы управления создаются динамически. Тем не менее, я могу искать визуальные и / или логические деревья и добираться до ...
  2. В событии GotFocus сохраните ссылку на элемент управления.
  3. Когда мы выходим из занятого состояния, попытайтесь установить фокус на сохраненный элемент управления.

Это работает ... своего рода Сорта. Проблема под рукой (как я могу подумать о большем количестве сценариев сбоя ...) заключается в том, что эта логика уничтожит контекстное меню, если оно было открыто, и другое. Рассмотрим:

  1. Фокус в текстовой области.
  2. Пользователь щелкает правой кнопкой мыши другой элемент управления. Этот элемент управления не получает фокус (даже если я пытаюсь установить его в обработчике мыши).
  3. Система переходит в состояние занятости, когда щелчок правой кнопкой мыши выполняет перемещение.
  4. Когда состояние занятости заканчивается, текстовая область получает фокус, и контекстное меню закрывается.

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

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

Ответы [ 5 ]

10 голосов
/ 26 июня 2011

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

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

3 голосов
/ 30 июня 2011

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

if(!bControlsEnabled) { return; }

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

1 голос
/ 13 марта 2019

Обходной путь для этого: - Вместо отключения элемента управления Вы должны использовать XamBusyIndicator в качестве родителя этого элемента управления и установить свойство для IsBusy.Если IsBusy имеет значение true, он отключит дочерний элемент управления, а также свойство TabIndex будет работать разумным образом.Например: -

<igComboEditor:XamBusyIndicator IsBusy="{Binding IsBusy}" Height="22">
                                <igComboEditor:XamBusyIndicator.Animation>
                                    <igComboEditor:CustomBusyAnimation DataTemplate="{StaticResource CustomBusyIndicatorTemplate}" />
                                </igComboEditor:XamBusyIndicator.Animation>
                                <igComboEditor:XamComboEditor Width="125"  VerticalAlignment="Bottom" Style="{StaticResource XamComboEditorStyle}"
                                                          ItemsSource="{Binding DataList}" IsEditable="False" 
                                                          SelectedItem="{Binding SelectedData}">

                            </igComboEditor:XamComboEditor>
                            </igComboEditor:XamBusyIndicator>
1 голос
/ 27 июня 2011

Реализуйте пользовательское поведение, которое прослушивает, когда изменяется включенный элемент управления, сохраняет сфокусированный элемент и перефокусирует этот элемент, когда включенный изменяется обратно на true:

public class KeyboardFocus
{
    public static bool GetReturnFocusAfterEnable(DependencyObject obj)
    {
        return (bool)obj.GetValue(ReturnFocusAfterEnableProperty);
    }

    public static void SetReturnFocusAfterEnable(DependencyObject obj, bool value)
    {
        obj.SetValue(ReturnFocusAfterEnableProperty, value);
    }

    private static Dictionary<object, IInputElement> values = new Dictionary<object, IInputElement>();

    // Using a DependencyProperty as the backing store for ReturnFocusAfterEnable.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ReturnFocusAfterEnableProperty =
        DependencyProperty.RegisterAttached("ReturnFocusAfterEnable", typeof(bool), typeof(KeyboardFocus), new UIPropertyMetadata(false, PropertyChangedCallback));

    static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
        {
            UIElement element = d as UIElement;
            if (element != null)
            {
                element.IsEnabledChanged += (element_IsEnabledChanged);
            }

        }
        else
        {
            UIElement element = d as UIElement;
            if (element != null)
            {
                element.IsEnabledChanged -= (element_IsEnabledChanged);
            }

        }
    }

    static void element_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if ((bool)e.NewValue)
        {
            if (values.ContainsKey(sender))
            {
                Keyboard.Focus(values[sender]);
                values.Remove(sender);
            }
        }
        else
        {
            values[sender] = Keyboard.FocusedElement;
        }            
    }
}

Это может быть реализовано в XAML следующим образом:

<Grid Name="layout" local:KeyboardFocus.ReturnFocusAfterEnable="True">

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

Это решение не зависит от вашей архитектуры и не требует кода в форме. Это немного быстро и грязно, но это делает работу.

0 голосов
/ 30 июня 2011

Я бы

OnCommandSentThatRequiresAWait Event Call SaveStateAndDisableUI()

SaveStateAndDisableUI()
{
   Foreach control in controlsCollection
   {
       switch(controlType)
       {
           for each control extract and save all you need. 
           if it's a menu check if it is opened up and so on, 
           does control have focus, 
           where is the caret located in case of textbox etc              
       }
   }
   save position of mouse x,y
   save position of form, state like if it is minimized, maximized
}

Corresponding RestoreState() should restore everything back up.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...