2008-08-11 23 views
7

इंस्ट्रूमेंटिंग आप अपने यूआई का वाद्य यंत्र कैसे बना रहे हैं? अतीत में मैंने पढ़ा है कि लोगों ने अपने उपयोगकर्ता इंटरफेस का वादा किया है, लेकिन जो मुझे नहीं मिला है वह यूआई के उपकरण के लिए पर पर उदाहरण या सुझाव है।यूआई

उपकरण से, मेरा मतलब है सिस्टम के उपयोग और प्रदर्शन के संबंध में डेटा एकत्र करना। इंस्ट्रुमेंटेशन पर एक एमएसडीएन आलेख http://msdn.microsoft.com/en-us/library/x5952w0c.aspx है। मैं यह जानना चाहता हूं कि कौन से बटन उपयोगकर्ता क्लिक करते हैं, वे किस कुंजीपटल का उपयोग करते हैं, वे किस शब्द का उपयोग करते हैं, आदि

  • आप अपने यूआई का वाद्य यंत्र कैसे बना रहे हैं?
  • आप किस प्रारूप को उपकरण संग्रहित कर रहे हैं?
  • आप वाद्य यंत्र को कैसे संसाधित कर रहे हैं?
  • आप अपने यूआई कोड को इस उपकरण तर्क के साथ कैसे साफ रखते हैं?

विशेष रूप से, मैं डब्ल्यूपीएफ में अपना यूआई लागू कर रहा हूं, इसलिए यह वेब-आधारित एप्लिकेशन के उपकरण की तुलना में अतिरिक्त चुनौतियों को प्रदान करेगा। (यानी वाद्य यंत्र को वापस केंद्रीय स्थान पर स्थानांतरित करने की आवश्यकता है)। उस ने कहा, मुझे लगता है कि तकनीक संलग्न गुणों जैसे अवधारणाओं के माध्यम से वाद्ययंत्र का एक आसान कार्यान्वयन प्रदान कर सकती है।

  • क्या आपने एक WPF एप्लिकेशन का वाद्य यंत्र किया है? क्या आपके पास कोई सुझाव है कि यह कैसे प्राप्त किया जा सकता है?

संपादित करें: निम्न ब्लॉग पोस्ट एक दिलचस्प समाधान प्रस्तुत करता है: Pixel-In-Gene Blog: Techniques for UI Auditing on WPF apps

उत्तर

2

निम्न ब्लॉग पोस्ट एक WPF अनुप्रयोग के उपकरण के लिए कुछ अच्छे विचार देता है: Techniques for UI Auditing on WPF apps

+0

EventManager.RegisterClassHandler वास्तव में चाल किया था। – angularsen

+0

मैं सिर्फ एक लिंक प्रदान करना चाहता था जो मेरे लिए काम करता था: http://blog.pixelingene.com/2008/08/techniques-for-ui-auditing-on-wpf-apps/ –

-1

मैं अभी तक WPF का उपयोग कर विकास नहीं किया है .. लेकिन मुझे लगता है कि अपने आप चाहते हैं कि में सबसे अन्य अनुप्रयोगों के रूप में ही ग्रहण करेंगे UI कोड को यथासंभव प्रकाश के रूप में रखने के लिए .. इसमें कई डिज़ाइन पैटर्न का उपयोग किया जा सकता है जैसे स्पष्ट MVC और Façade। मैं व्यक्तिगत रूप से हमेशा यूआई और बीएल परतों के बीच यात्रा के रूप में यात्रा करने की कोशिश करता हूं और उन्हें प्राथमिकता देता हूं, यदि मैं कर सकता हूं।

.. यह तो मुझे कुछ भी की चिंताओं को एक बार मैं अपने (आदिम) डेटा को वापस भेज चल रहा बिना यूआई परत को सुधारने पर ध्यान में मदद करता है

मुझे आशा है कि मैं सही ढंग से अपने प्रश्न समझ में आया, और खेद मैं और अधिक की पेशकश नहीं कर सकते डब्ल्यूपीएफ के साथ प्रासंगिक मदद।

2

आप log4net पर विचार कर सकते हैं। यह एक मजबूत लॉगिंग ढांचा है जो एक एकल डीएलएल में मौजूद है। यह "गैर मांग" प्रकार मोड में भी किया जाता है ताकि यदि कोई महत्वपूर्ण प्रक्रिया चल रही है, तो यह तब तक लॉग नहीं होगा जब तक संसाधनों को थोड़ा और मुक्त नहीं किया जाता है।

आप आसानी से INFO स्तर लॉगर्स का एक समूह स्थापित कर सकते हैं और आपको आवश्यक सभी उपयोगकर्ता इंटरैक्शन ट्रैक कर सकते हैं, और फ़ाइल को स्वयं भेजने के लिए यह एक बग क्रैश नहीं करेगा। फिर आप फ़ाइल को अलग करने के लिए अपने सभी त्रुटि और FATAL कोड को लॉग भी कर सकते हैं जो आसानी से प्रसंस्करण के लिए आपको मेल किया जा सकता है।

2

यदि आप WPF आदेशों का उपयोग करते हैं, तो प्रत्येक कस्टम कमांड तब कार्रवाई की गई लॉग को लॉग कर सकता है। आप कमांड शुरू करने के तरीके को भी लॉग कर सकते हैं।

0

शायद WP12 के लिए Microsoft UI Automation मदद कर सकता है? यह आपके यूआई को स्वचालित करने के लिए एक ढांचा है, शायद इसका उपयोग आपके लिए सामान लॉग करने के लिए किया जा सकता है ...

हम WPF में हमारे UI को स्वत: परीक्षण के लिए ऑटोमेशन फ्रेमवर्क का उपयोग करते हैं।

0

अस्वीकरण: मैं इस उत्पाद को बेचने वाली कंपनी के लिए काम करता हूं, न केवल यह कि मैं इस विशेष उत्पाद पर डेवलपर हूं :)।

यदि आप इसे प्रदान करने के लिए एक वाणिज्यिक उत्पाद में रूचि रखते हैं तो रनटाइम इंटेलिजेंस (डॉटफुस्केटर पर एक कार्यात्मक जोड़) जो आपके .NET अनुप्रयोगों में उपयोग ट्रैकिंग कार्यक्षमता को इंजेक्ट करता है। हम न केवल ट्रैकिंग कार्यक्षमता के वास्तविक कार्यान्वयन प्रदान करते हैं बल्कि डेटा संग्रहण, प्रसंस्करण और रिपोर्टिंग कार्यक्षमता भी प्रदान करते हैं।

हाल ही में इस विषय पर सॉफ्टवेयर फोरम के व्यवसाय पर एक चर्चा हुई थी जिसे मैंने यहां भी पोस्ट किया था: http://discuss.joelonsoftware.com/default.asp?biz.5.680205.26

हमारी सामग्री के उच्च स्तर के अवलोकन के लिए यहां देखें: http://www.preemptive.com/runtime-intelligence-services.html

इसके अतिरिक्त मैं वर्तमान में कुछ और तकनीकी रूप से उन्मुख दस्तावेज लिखने पर काम कर रहा हूं क्योंकि हमें पता है कि एक ऐसा क्षेत्र है जहां हम निश्चित रूप से सुधार कर सकते हैं, कृपया मुझे बताएं कि अगर कोई इसे पूरा कर लेता है तो मुझे अधिसूचित होने में दिलचस्पी है।

3

यहां एक उदाहरण है कि मैं यूआई घटनाओं पर हुक करने के लिए एक सरल घटना प्रबंधक का उपयोग कैसे करता हूं और घटनाओं की महत्वपूर्ण जानकारी जैसे कि नाम और यूआई तत्व के प्रकार, घटना का नाम और मूल विंडो के प्रकार का नाम निकालने का उदाहरण देता हूं। सूचियों के लिए मैं चयनित आइटम भी निकालता हूं।

यह समाधान केवल बटनबेज (बटन, टॉगल बटन, ...) से प्राप्त नियंत्रणों के चयन और चयनकर्ता (सूची बॉक्स, टैबकंट्रोल, ...) से प्राप्त नियंत्रणों में चयन परिवर्तनों के लिए सुनता है। अन्य प्रकार के यूआई तत्वों को विस्तारित करना या अधिक सुगंधित समाधान प्राप्त करना आसान होना चाहिए। समाधान Brad Leach's answer से प्रेरित है।

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 का उपयोग करें और उपयोगकर्ता संपर्क लॉग इन करने की 'बातचीत' नामक एक अलग लकड़हारा बनाया। यहां लॉग 'क्लास' लॉग 4net के लिए मेरा अपना स्थिर आवरण है।

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