Инструментирование пользовательского интерфейса - PullRequest
7 голосов
/ 12 августа 2008

Как вы управляете своим пользовательским интерфейсом? В прошлом я читал, что люди инструментировали свои пользовательские интерфейсы, но я не нашел примеров или советов по , как как использовать пользовательский интерфейс.

Под инструментами я подразумеваю сбор данных об использовании и производительности системы. Статья MSDN по инструментам: http://msdn.microsoft.com/en-us/library/x5952w0c.aspx. Я хотел бы описать, какие кнопки нажимают пользователи, какие сочетания клавиш они используют, какие термины используют для поиска и т. Д.

  • Как вы настраиваете свой пользовательский интерфейс?
  • В каком формате вы храните контрольно-измерительные приборы?
  • Как вы обрабатываете инструментальные данные?
  • Как вы храните свой код пользовательского интерфейса в чистоте с помощью этой логики инструментария?

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

  • Инструментировали ли вы приложение WPF? Есть ли у вас какие-либо советы о том, как этого можно достичь?
<ч />

Редактировать: следующее сообщение в блоге представляет интересное решение: Блог Pixel-In-Gene: методы аудита пользовательского интерфейса в приложениях WPF

Ответы [ 7 ]

3 голосов
/ 13 апреля 2011

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

Это решение прослушивает только щелчки элементов управления, полученных из ButtonBase (Button, ToggleButton, ...), и изменения выбора в элементах управления, полученных из Selector (ListBox, TabControl, ...). Это должно быть легко распространено на другие типы элементов пользовательского интерфейса или для достижения более мелкозернистого решения. Решение основано на ответе Брэда Лича .

public class UserInteractionEventsManager
{
    public delegate void ButtonClickedHandler(DateTime time, string eventName, string senderName, string senderTypeName, string parentWindowName);
    public delegate void SelectorSelectedHandler(DateTime time, string eventName, string senderName, string senderTypeName, string parentWindowName, object selectedObject);

    public event ButtonClickedHandler ButtonClicked;
    public event SelectorSelectedHandler SelectorSelected;

    public UserInteractionEventsManager()
    {
        EventManager.RegisterClassHandler(typeof(ButtonBase), ButtonBase.ClickEvent, new RoutedEventHandler(HandleButtonClicked));
        EventManager.RegisterClassHandler(typeof(Selector), Selector.SelectionChangedEvent, new RoutedEventHandler(HandleSelectorSelected));
    }

    #region Handling events

    private void HandleSelectorSelected(object sender, RoutedEventArgs e)
    {
        // Avoid multiple events due to bubbling. Example: A ListBox inside a TabControl will cause both to send the SelectionChangedEvent.
        if (sender != e.OriginalSource) return;

        var args = e as SelectionChangedEventArgs;
        if (args == null || args.AddedItems.Count == 0) return;

        var element = sender as FrameworkElement;
        if (element == null) return;

        string senderName = GetSenderName(element);
        string parentWindowName = GetParentWindowTypeName(sender);
        DateTime time = DateTime.Now;
        string eventName = e.RoutedEvent.Name;
        string senderTypeName = sender.GetType().Name;
        string selectedItemText = args.AddedItems.Count > 0 ? args.AddedItems[0].ToString() : "<no selected items>";

        if (SelectorSelected != null)
            SelectorSelected(time, eventName, senderName, senderTypeName, parentWindowName, selectedItemText);
    }

    private void HandleButtonClicked(object sender, RoutedEventArgs e)
    {
        var element = sender as FrameworkElement;
        if (element == null) return;

        string parentWindowName = GetParentWindowTypeName(sender);
        DateTime time = DateTime.Now;
        string eventName = e.RoutedEvent.Name;
        string senderTypeName = sender.GetType().Name;
        string senderName = GetSenderName(element);

        if (ButtonClicked != null) 
            ButtonClicked(time, eventName, senderName, senderTypeName, parentWindowName);
    }

    #endregion

    #region Private helpers

    private static string GetSenderName(FrameworkElement element)
    {
        return !String.IsNullOrEmpty(element.Name) ? element.Name : "<no item name>";
    }


    private static string GetParentWindowTypeName(object sender)
    {
        var parent = FindParent<Window>(sender as DependencyObject);
        return parent != null ? parent.GetType().Name : "<no parent>";
    }

    private static T FindParent<T>(DependencyObject item) where T : class
    {
        if (item == null) 
            return default(T);

        if (item is T)
            return item as T;

        DependencyObject parent = VisualTreeHelper.GetParent(item);
        if (parent == null)
            return default(T);

        return FindParent<T>(parent);
    }

    #endregion
}

А для ведения реальной регистрации я использую log4net и создал отдельный регистратор с именем «Взаимодействие» для регистрации взаимодействия с пользователем. Класс 'Log' здесь - просто моя собственная статическая оболочка для log4net.

/// <summary>
/// The user interaction logger uses <see cref="UserInteractionEventsManager"/> to listen for events on GUI elements, such as buttons, list boxes, tab controls etc.
/// The events are then logged in a readable format using Log.Interaction.Info().
/// </summary>
public class UserInteractionLogger
{
    private readonly UserInteractionEventsManager _events;
    private bool _started;

    /// <summary>
    /// Create a user interaction logger. Remember to Start() it.
    /// </summary>
    public UserInteractionLogger()
    {
        _events = new UserInteractionEventsManager();

    }

    /// <summary>
    /// Start logging user interaction events.
    /// </summary>
    public void Start()
    {
        if (_started) return;

        _events.ButtonClicked += ButtonClicked;
        _events.SelectorSelected += SelectorSelected;

        _started = true;
    }

    /// <summary>
    /// Stop logging user interaction events.
    /// </summary>
    public void Stop()
    {
        if (!_started) return;

        _events.ButtonClicked -= ButtonClicked;
        _events.SelectorSelected -= SelectorSelected;

        _started = false;
    }

    private static void SelectorSelected(DateTime time, string eventName, string senderName, string senderTypeName, string parentWindowTypeName, object selectedObject)
    {
        Log.Interaction.Info("{0}.{1} by {2} in {3}. Selected: {4}", senderTypeName, eventName, senderName, parentWindowTypeName, selectedObject);
    }

    private static void ButtonClicked(DateTime time, string eventName, string senderName, string senderTypeName, string parentWindowTypeName)
    {
        Log.Interaction.Info("{0}.{1} by {2} in {3}", senderTypeName, eventName, senderName, parentWindowTypeName);
    }
}

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

04/13 08:38:37.069 INFO        Iact ToggleButton.Click by AnalysisButton in MyMainWindow
04/13 08:38:38.493 INFO        Iact ListBox.SelectionChanged by ListView in MyMainWindow. Selected: Andreas Larsen
04/13 08:38:44.587 INFO        Iact Button.Click by EditEntryButton in MyMainWindow
04/13 08:38:46.068 INFO        Iact Button.Click by OkButton in EditEntryDialog
04/13 08:38:47.395 INFO        Iact ToggleButton.Click by ExitButton in MyMainWindow
2 голосов
/ 28 августа 2008

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

2 голосов
/ 12 августа 2008

Если вы используете команды WPF, каждая пользовательская команда может затем записать выполненное действие. Вы также можете записать способ инициализации команды.

2 голосов
/ 12 августа 2008

Вы можете рассмотреть log4net . Это надежная структура ведения журнала, которая существует в одной DLL. Это также делается в режиме «нетребовательного» типа, так что если происходит критический процесс, он не будет регистрироваться, пока ресурсы не будут освобождены немного больше.

Вы можете легко настроить связку регистраторов уровня INFO и отследить все взаимодействие с пользователем, в котором вы нуждаетесь, и для отправки файла вам не понадобится ошибка. Затем вы можете также записать весь свой код ОШИБКИ и ФАТАЛЬНО в отдельный файл, который можно легко отправить вам по почте для обработки.

0 голосов
/ 03 октября 2008

Отказ от ответственности: я работаю в компании, которая продает этот продукт, не только, но я являюсь разработчиком этого конкретного продукта :).

Если вы заинтересованы в коммерческом продукте, обеспечивающем это, тогда доступна Runtime Intelligence (функциональная надстройка для Dotfuscator), которая добавляет функциональность отслеживания использования в ваши приложения .NET. Мы обеспечиваем не только фактическую реализацию функций отслеживания, но и функции сбора, обработки и отчетности.

Недавно на форуме «Бизнес программного обеспечения» обсуждалась тема, которую я также разместил здесь: http://discuss.joelonsoftware.com/default.asp?biz.5.680205.26.

Общий обзор наших вещей см. Здесь: http://www.preemptive.com/runtime-intelligence-services.html.

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

0 голосов
/ 12 августа 2008

Может быть, Microsoft UI Automation для WPF может помочь? Это фреймворк для автоматизации вашего пользовательского интерфейса, возможно, его можно использовать для записи материалов для вас ...

Мы используем Automation Framework для автоматического тестирования нашего пользовательского интерфейса в WPF.

0 голосов
/ 12 августа 2008

Я еще не разработал с использованием WPF. Но я бы предположил, что он такой же, как и большинство других приложений, в котором вы хотите, чтобы код пользовательского интерфейса был как можно более легким. В этом как очевидные MVC и Фасад . Лично я всегда стараюсь, чтобы объекты, перемещающиеся между слоями пользовательского интерфейса и BL, были как можно более легкими, сохраняя их примитивами, если я могу.

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

Надеюсь, я правильно понял ваш вопрос, и извините, я не могу предложить более контекстную помощь с WPF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...