Подтвердить что ты не робот

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

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

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

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

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

Ответ 2

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

if(!bControlsEnabled) { return; }

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

Ответ 3

Внедрение пользовательского поведения, которое слушает, когда ваш контроль включен, сохраняет сфокусированный элемент и переориентирует этот элемент, когда он включен, возвращается к 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">

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

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

Ответ 4

Я бы

OnCommandSentThatRequiresAWait Event Call SaveStateAndDisableUI()

SaveStateAndDisableUI()
{
   Foreach control in controlsCollection
   {
       switch(controlType)
       {
           for each control extract and save all you need. 
           if it 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.