WPF अनुप्रयोगों के निर्माण के लगभग पूरे समय मैं
प्रतिक्रियाशील और
preventative समाधान की एक किस्म एकत्र किया सुनिश्चित करना है कि
सब कुछ एक साथ ठीक से बांध के पिछले 3 वर्षों में
।
नोट:
मैं तुम्हें एक त्वरित सारांश अब देना और फिर सुबह में वापस पोस्ट कोड नमूने/स्क्रीनशॉट के साथ (10 घंटे के समय में) होगा।
1) एक कनवर्टर कि डिबगर टूट जाता है जब
Convert
और
ConvertBack
निष्पादित किया जाता है बनाएँ:
ये मेरी सबसे प्रभावी उपकरण हैं। यह सुनिश्चित करने के लिए एक त्वरित और उपयोगी तरीका है कि आपके पास मूल्यों की अपेक्षा है। मैंने पहली बार इस चाल के बारे में Bea Stollnitz's blog post से सीखा।
DebugConverter.cs
public class DebugConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (Debugger.IsAttached)
Debugger.Break();
return Binding.DoNothing;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (Debugger.IsAttached)
Debugger.Break();
return Binding.DoNothing;
}
}
2) एक TraceListener
कि किसी भी त्रुटि को बीच में रोक बनाएँ। जब आप डीबगर संलग्न होते हैं तो यह विजुअल स्टूडियो आउटपुट विंडो में जो दिखाई देता है उसके समान होता है। बाध्यकारी ऑपरेशन के दौरान एक अपवाद फेंकने पर इस विधि का उपयोग करके मैं डीबगर को तोड़ने के लिए प्राप्त कर सकता हूं। यह PresentationTraceSources.TraceLevel
सेट करने से बेहतर है क्योंकि यह पूरे एप्लिकेशन पर लागू होता है, प्रति बाध्यकारी नहीं।
DataBindingErrorLogger।सीएस
public class DataBindingErrorLogger : DefaultTraceListener, IDisposable
{
private ILogger Logger;
public DataBindingErrorLogger(ILogger logger, SourceLevels level)
{
Logger = logger;
PresentationTraceSources.Refresh();
PresentationTraceSources.DataBindingSource.Listeners.Add(this);
PresentationTraceSources.DataBindingSource.Switch.Level = level;
}
public override void Write(string message)
{
}
public override void WriteLine(string message)
{
Logger.BindingError(message);
if (Debugger.IsAttached && message.Contains("Exception"))
Debugger.Break();
}
protected override void Dispose(bool disposing)
{
Flush();
Close();
PresentationTraceSources.DataBindingSource.Listeners.Remove(this);
}
}
प्रयोग
DataBindingErrorLogger = new DataBindingErrorLogger(Logger, SourceLevels.Warning);
ऊपर में, ILogger
एक NLog लॉग लेखक है। मेरे पास DefaultTraceListener
का एक अधिक जटिल संस्करण है जो एक पूर्ण स्टैक ट्रेस की रिपोर्ट कर सकता है और वास्तव में अपवाद फेंक सकता है हालांकि यह आपको शुरू करने के लिए पर्याप्त होगा (जेसन बॉक के पास article on this extended implementation है यदि आप इसे स्वयं लागू करना चाहते हैं, हालांकि आपको वास्तव में कोड की आवश्यकता होगी इसे काम करें)।
3)Snoop WPF आत्मनिरीक्षण उपकरण का उपयोग अपने दृश्य में पहुंचने और अपनी डेटा ऑब्जेक्ट का निरीक्षण करने के लिए करें। स्नूप का उपयोग करके आप अपने दृश्य की तार्किक संरचना देख सकते हैं और विभिन्न स्थितियों का परीक्षण करने के लिए मूल्यों को अंतःक्रियात्मक रूप से बदल सकते हैं।
स्नूप WPF बिल्कुल जरूरी किसी भी WPF आवेदन की यात्रा समय के लिए है। इसकी कई विशेषताओं में से डेल्व कमांड आपको अपने दृश्य/दृश्य मॉडल पर ड्रिल करने और मूल्यों को अंतःक्रियात्मक रूप से ट्विक करने की अनुमति देता है। किसी संपत्ति में जाने के लिए, संदर्भ मेनू खोलने के लिए राइट-क्लिक करें और Delve कमांड का चयन करें; एक स्तर (अन-डेलव?) का बैक अप लेने के लिए शीर्ष-दाएं कोने में ^ एक छोटा बटन है। उदाहरण के लिए, DataContext
संपत्ति में delving करने का प्रयास करें।
संपादित करें: मैं विश्वास नहीं कर सकता मैं सिर्फ यह देखा, लेकिन वहाँ स्नूप WPF विंडो में एक डाटा प्रसंग टैब है।
4)#DEBUG
में INotifyPropertyChanged
घटनाओं पर रनटाइम जाँच करता है। चूंकि डेटा बाइंडिंग सिस्टम अधिसूचित होने पर निर्भर करता है जब गुण बदल जाते हैं, यह आपके स्वच्छता के लिए महत्वपूर्ण है कि आप यह सूचित कर रहे हैं कि सही संपत्ति बदल गई है। कुछ प्रतिबिंब जादू के साथ आप कुछ गलत होने पर Debug.Assert
कर सकते हैं।
PropertyChangedHelper.cs
public static class PropertyChangedHelper
{
#if DEBUG
public static Dictionary<Type, Dictionary<string, bool>> PropertyCache = new Dictionary<Type, Dictionary<string, bool>>();
#endif
[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, string propertyName)
{
sender.Notify(eventHandler, new PropertyChangedEventArgs(propertyName), true);
}
[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, string propertyName, bool validatePropertyName)
{
sender.Notify(eventHandler, new PropertyChangedEventArgs(propertyName), validatePropertyName);
}
[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, PropertyChangedEventArgs eventArgs)
{
sender.Notify(eventHandler, eventArgs, true);
}
[DebuggerStepThrough]
public static void Notify(this INotifyPropertyChanged sender, PropertyChangedEventHandler eventHandler, PropertyChangedEventArgs eventArgs, bool validatePropertyName)
{
#if DEBUG
if (validatePropertyName)
Debug.Assert(PropertyExists(sender as object, eventArgs.PropertyName), String.Format("Property: {0} does not exist on type: {1}", eventArgs.PropertyName, sender.GetType().ToString()));
#endif
// as the event handlers is a parameter is actually somewhat "thread safe"
// http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx
if (eventHandler != null)
eventHandler(sender, eventArgs);
}
#if DEBUG
[DebuggerStepThrough]
public static bool PropertyExists(object sender, string propertyName)
{
// we do not check validity of dynamic classes. it is possible, however since they're dynamic we couldn't cache them anyway.
if (sender is ICustomTypeDescriptor)
return true;
var senderType = sender.GetType();
if (!PropertyCache.ContainsKey(senderType))
PropertyCache.Add(senderType, new Dictionary<string,bool>());
lock (PropertyCache)
{
if (!(PropertyCache[senderType].ContainsKey(propertyName)))
{
var hasPropertyByName = (senderType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static) != null);
PropertyCache[senderType].Add(propertyName, hasPropertyByName);
}
}
return PropertyCache[senderType][propertyName];
}
#endif
}
HTH,
कोई प्रश्न, मुझे एक चिल्लाओ दे। – Dennis