문제

어떻게 당신은 계측 UI 니까?과거에는 내가 읽는 사람들이 계측이 그들의 사용자 인터페이스,그러나 내가 무엇을 발견하지 않았는 예제 또는 팁에 는 방법 계측 UI.

에 의해 계측,제 말은 데이터를 수집 및 사용에 관한 성능의 시스템입니다.MSDN 문서에 계측 http://msdn.microsoft.com/en-us/library/x5952w0c.aspx.고 싶을 캡처하는 버튼 사용자 클릭,무엇 키보드 shortucts,그들이 사용하는 용어들을 사용하여 검색,etc.

  • 어떻게 당신은 계측 UI?
  • 무슨 형식으로 저장하고 있습 계측?
  • 당신은 어떻게 처리된 데이터가?
  • 어떻게 당신을 유지하 UI 코드를 깨끗한 이 계측 logic?

특히,나를 구현하는 내 UI 에서 WPF 그래서 이렇게 추가 도전에 비해 계측하는 웹 기반 응용 프로그램입니다.(i.e하는 데 필요한 계측 데이터에 중앙 위치,etc.).는 말했다,나는 느낌은 기술을 제공할 수 있습니다 쉽게 구현 계측을 통해 개념 같은 첨부된 속성입니다.

  • 당신은 계측 WPF 응용 프로그램?당신은 어떤 끝에 어떻게 이것이 달성될 수 있다고 보십니까?

편집:다음과 같은 블로그 게시물 재미 솔루션: 픽셀에서 유전자 블로그:기술 UI 에 대한 감사를 WPF 앱

도움이 되었습니까?

해결책 4

다음과 같은 블로그 포스트를 제공합니다 좋은 아이디어를 계측하기 위한 응용 프로그램 WPF:기술 UI 에 대한 감사를 WPF 앱.

다른 팁

여기에 예를 들어 내가 어떻게 사용하여 간단한 이벤트를 관리하는 후크에 UI 이벤트와 추출물 주요 정보의 이벤트와 같이 이름과 형식의 UI 요소의 이름 이벤트 부모 창의 형식 이름입니다.위 목록 나도 추출을 선택 항목입니다.

이 솔루션만을 수신한 클릭의 제어에서 파생된 ButtonBase(버튼,토글,...)및 선택에 변경이트에서 파생된 선택(ListBox,TabControl,...).그것은 쉽게 해야를 확장하여 다른 형태의 UI 요소 또는 달성하기 위해 좀 더 세분화된 솔루션입니다.이 솔루션은 영감의 브래드 리치의 응답.

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 고 만들어진 별도로거 라는'상호'로그인 사용자 상호 작용입니다.클래스'로그인'여기에는 단순히 내 자신의 정적에 대한 래퍼 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

고려할 수 있습니다 log4net.그것은 강력한 프레임 워크를 로깅에 존재하는 단 하나 DLL.그것은 또한에서 수행하는"비 요구"입력 모드를 경우 중요한 프로세스가 진행되지 않습니다에 로그인할 때까지 리소스를 해제 조금 더 있습니다.

당신은 쉽게 설치 무리의 정보 수준을 로거와 궤도 모든 사용자 상호 작용은 당신이 필요하며,그것은이 걸리지 않으면 버그가 충돌하면 파일을 전송합니다.당신은 또한 다음 로그의 모든 오류가와 치명적인 코드는 별도의 수 있는 파일을 쉽게 송부하를 처리합니다.

만약 당신의 사용 WPF 명령을 각 사용자 정의 명령을 수 있는 그런 다음 로그습니다.로그인할 수도 있습 방법을 명령이 시작되었다.

Microsoft UI 자동화 WPF 도울 수 있습니까?그는 프레임워크를 자동화 하기 위한 UI,아마도 그것이 로그인하는 데 사용할 수 있습니다 물건은 당신을 위해...

우리가 사용하여 자동화 프레임워크에 대한 자동 테스트는 우리의 WPF UI.

면책 조항:저는 작품을 위해 회사가 판매하는 이 제품,뿐만 아니라 하지만 나는 개발자는 이 특별한 제품:).

에 관심이 있는 경우에는 상업적인 제품을 제공하이 후타 지(기능에 추가하 Dotfuscator)주사하는 사용 추적 기능으로 귀하의.NET 응용 프로그램을 사용할 수 있습니다.우리가 제공뿐만 아니라 실제 구현한 추적 기능을 하지만 데이터 수집,처리 및 보고 기능을 뿐입니다.

이 있었다 최근에 논의 비즈니스에 소프트웨어 포럼에 이 주제는 나도시에 위치한 여기: http://discuss.joelonsoftware.com/default.asp?biz.5.680205.26 .

에 대한 높은 수준의 개요 우리의 물건은 여기를 참조하십시오: http://www.preemptive.com/runtime-intelligence-services.html .

또한 저는 현재 쓰기에 약간 더 기술적으로 중심으로서 우리는 영역입니다 우리는 확실히 개선으면 알려 주시기 바랍에 관심이 있는 사람이 통지를 받은 때 내가 완료했습니다.

저는 아직도 사용하여 개발 WPF..그러나 나는 가정으로 대부분의 다른 응용 프로그램에서 유지하려면 원하는 UI 코드 빛으로 가능합니다..숫자의 디자인 패턴에서 사용할 수 있습은 이와 같은 명백한 MVC외관.나 개인적으로 항상 노력하고 유지하는 물체 사이에 여행 UI BL 층으로 빛으로 가능한 유지하는 기본 형식으면 내가 할 수 있습니다.

이 다음에 집중하는 데 도움이 개선 UI 층 걱정 없이 아무것도의 것에 한 번 보았다(기본)데이다.

나는 이해 당신의 질문을 올바르게,그리고 미을 제공 할 수 없습니다 더 많은 상황에 맞는 도움말 WPF.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top