2010-02-18 4 views
7

मैं अपने द्वारा बनाए गए उपयोगकर्ता नियंत्रण का परीक्षण करने के बीच में हूं, और मुझे ऐसा कुछ मिल रहा है जो मेरे लिए अतुलनीय है।बाइंडिंग पर नो-ऑप कनवर्टर डालने का व्यवहार क्यों बदलता है?

नियंत्रण कॉम्बोबॉक्स का एक विस्तार है जो एक विशिष्ट कस्टम प्रकार के मानों को संभालता है। इसमें उस कस्टम प्रकार की निर्भरता संपत्ति है जो बाध्यकारी की लक्षित संपत्ति है।

मुझे सेटटर में एक ट्रेस स्टेटमेंट मिला है, और मैं देख सकता हूं कि संपत्ति सेट हो रही है। लेकिन यह मेरे उपयोगकर्ता नियंत्रण में नहीं दिख रहा है।

अब, आमतौर पर मैं कहूंगा, ठीक है, मेरे उपयोगकर्ता नियंत्रण में मुझे एक बग मिला है। मैं शायद ऐसा करता हूं, हालांकि मैं इसके बारे में परेशान हूं। लेकिन यह सवाल मेरे नियंत्रण में बग खोजने के बारे में नहीं है। पढ़ते रहिये; यहां वह अजीब हो जाता है।

मैं भी बिया Stollnitz के कम मूल्य कनवर्टर का उपयोग कर रहा डिबग मदद करने के लिए बाइंडिंग:

public class DebuggingConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     return value; // Add the breakpoint here!! 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException("This method should never be called"); 
    } 
} 

इसके पीछे विचार है कि मैं अपने बाइंडिंग को यह कनवर्टर जोड़ सकते हैं और देखने के लिए क्या मूल्य है एक ब्रेकपाइंट सेट कर सकते हैं लक्ष्य के लिए बाहर धकेल दिया जा रहा है। ठीक है, यह ठीक काम करता है। मैं देख सकता हूं कि मूल्य धक्का दिया जा रहा है।

वास्तव में, यह भी ठीक काम करता है। यदि डिबगिंग कनवर्टर बाध्यकारी से जुड़ा हुआ है, तो उपयोगकर्ता नियंत्रण मान प्रदर्शित करता है। यदि ऐसा नहीं है, तो यह नहीं है।

यह भी कैसे संभव है? एक मूल्य कनवर्टर कैसे कुछ भी बाध्य नियंत्रण के व्यवहार को प्रभावित नहीं कर सकता है?

संपादित करें:

ऐसा नहीं है कि यह मदद करने के लिए होने की संभावना है, लेकिन यहां उपयोगकर्ता नियंत्रण के लिए XAML है:

<a:CodeLookupBox 
    Grid.Column="1" 
    Grid.IsSharedSizeScope="True" 
    MinWidth="100" 
    Style="{Binding Style}"> 
    <a:CodeLookupBox.CodeLookupTable> 
     <Binding Path="Codes" Mode="OneWay"/> 
    </a:CodeLookupBox.CodeLookupTable> 
    <a:CodeLookupBox.SelectedCode> 
     <Binding Path="Value" Mode="TwoWay" ValidatesOnDataErrors="True"/> 
    </a:CodeLookupBox.SelectedCode> 
</a:CodeLookupBox> 

दूसरा बंधन पर कनवर्टर के बिना, नियंत्रण बर्ताव करता है जैसे कि मैं नहीं था SelectedCode सेट नहीं है। भले ही OnSelectedCodePropertyChanged हैंडलर में एक ट्रेस स्टेटमेंट दिखाता है कि e.Value में वास्तव में सही मान होता है। यह कनवर्टर संलग्न है या नहीं, भले ही यह होता है।

मैं इस समस्या को एक विचार प्रयोग के साथ उलटा करने की कोशिश कर रहा हूं: यदि आप एक बाध्य उपयोगकर्ता नियंत्रण बनाना चाहते हैं जिसका व्यवहार बदल गया है तो यदि कोई बाध्यकारी से कोई-ऑप कनवर्टर संलग्न नहीं होता है, तो आप इसे कैसे करेंगे? मैं जवाब के साथ आने के लिए बाध्यकारी के बारे में पर्याप्त नहीं जानता।

+1

यह बहुत दिलचस्प है:

संपादित

यहाँ संपत्ति घोषणाओं की तरह लग रही है। किसी भी तरह से आप बाइंडिंग दिखाने के लिए वहां कुछ एक्सएएमएल पेस्ट कर सकते हैं? –

+0

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

+0

क्षमा करें मैं आपकी मदद नहीं कर सकता, लेकिन +1 कारण है कि डिबगिंग कनवर्टर एक अच्छा विचार है (भले ही यह आपका विचार न हो)। –

उत्तर

2

अच्छा, अच्छी खबर यह है कि मुझे पता है कि SelectedCode सेट नहीं किया जा रहा है जब मैं एक मूल्य कनवर्टर का उपयोग नहीं कर रहा हूं। बुरी खबर यह है कि मेरे पास अभी भी एक रहस्य है, लेकिन समस्या को खाद्य श्रृंखला को थोड़ा सा धक्का दिया गया है, और मेरे पास एक कामकाज है।

यह नियंत्रण अनिवार्य रूप से एक दृढ़ता से टाइप किए गए कॉम्बो बॉक्स है जिसमें अतिरिक्त सुविधाओं का एक समूह है जो इस तथ्य से संभव है कि यह जानता है कि इसमें किस प्रकार की वस्तुएं हैं। SelectedCode और CodeLookupTable गुणों को दृढ़ता से टाइप किया गया है, और वे अंतर्निहित SelectedItem और ItemsSource गुणों को छिपाते हैं, जो नहीं हैं। (यह वैसे, यही कारण है कि यह उपयोगकर्ता नियंत्रण है और ComboBox का सबक्लास नहीं है; मैं नहीं चाहता कि उन गुणों को दिखाना पड़े क्योंकि बहुत सी चीजें तब हो सकती हैं जब वे अनुचित तरीके से सेट हो जाएं, उनमें से कोई भी अच्छा नहीं है।)

यहां क्या हो रहा है।

14626603: OnCodeLookupTablePropertyChanged 
    CodeLookupTable property set to Proceedings.Model.CodeLookupTable 
    box.MainComboBox.ItemsSource = MS.Internal.Data.EnumerableCollectionView 
14626603: OnSelectedCodePropertyChanged: 
    SelectedCode property set to Unlicensed Driver [VC12500(A)] 
    box.MainComboBox.ItemsSource = MS.Internal.Data.EnumerableCollectionView 

यह: यह मेरा डिबगिंग आउटपुट जब मूल्य कनवर्टर जुड़ा हुआ है (संख्या, नियंत्रण के हैश कोड है, क्योंकि मैं उनमें से एक गुच्छा है कि सभी एक साथ तैयार हो जाओ जब कार्यक्रम के प्रारंभ मिल गया है) है अपेक्षित व्यवहार है। CodeLookupTable संपत्ति सेट की गई है, इसलिए उस संग्रह में से किसी एक आइटम में SelectedCode सेटिंग को SelectedItem अंतर्निहित ComboBox पर सही ढंग से सेट करता है।

लेकिन मूल्य कनवर्टर के बिना, हम इस मिल:

16143157: OnSelectedCodePropertyChanged: 
    SelectedCode property set to Unlicensed Driver [VC12500(A)] 
    box.MainComboBox.ItemsSource = 
16143157: OnCodeLookupTablePropertyChanged 
    CodeLookupTable property set to Proceedings.Model.CodeLookupTable 
    box.MainComboBox.ItemsSource = MS.Internal.Data.EnumerableCollectionView 

यहाँ, SelectedCode गुण सेट किया जा रहा है से पहले CodeLookupTable संपत्ति है। तो जब विधि SelectedItem को अंतर्निहित ComboBox पर सेट करने का प्रयास करती है, तो कुछ भी नहीं होता है, क्योंकि ItemsSource शून्य है।

और यहां समस्या की जड़ है। मैंने मूर्खता से यह माना है कि बाइंडिंग्स में अपना लक्ष्य अपडेट करने का आदेश एक्सएएमएल में घोषित आदेश के समान है। (गुणों के बजाय तत्वों के रूप में बाइंडिंग को व्यक्त करने के कारणों में से एक कारण यह है कि किसी XML दस्तावेज़ में तत्वों का क्रम निर्धारक है और गुणों का क्रम नहीं है। ऐसा नहीं है कि मैंने इसके बारे में नहीं सोचा था।) यह स्पष्ट रूप से मामला नहीं है।

मैंने यह भी माना है कि शायद थोड़ा कम मूर्खतापूर्ण है कि जिस क्रम में बाइंडिंग अपने लक्ष्य को अपडेट करते हैं, वह इस बात पर निर्भर नहीं है कि वे मूल्य परिवर्तक संलग्न हैं या नहीं। यह ठीक है। मुझे आश्चर्य है कि यह और क्या निर्भर करता है।

दयालुता, मेरे पास इस के आसपास काम करने का एक तरीका है। चूंकि मेरे CodeLookup ऑब्जेक्ट में CodeLookupTable का संदर्भ है, इसलिए मैं SelectedCode सेटर CodeLookupTable (और इस प्रकार ItemsSource) संपत्ति को पहले सेट कर सकता हूं, अगर यह पहले से सेट नहीं किया गया है। यह बाध्यकारी पर एक नकली मूल्य कनवर्टर छड़ी किए बिना इस समस्या को दूर कर देगा और आशा करता है कि जिस तरह से बाइंडिंग व्यवहार कभी नहीं बदलता है।

#region SelectedCode 

public static readonly DependencyProperty SelectedCodeProperty = DependencyProperty.Register(
    "SelectedCode", typeof(CodeLookup), typeof(CodeLookupBox), 
    new FrameworkPropertyMetadata(OnSelectedCodePropertyChanged)); 

private static void OnSelectedCodePropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) 
{ 
    CodeLookupBox box = (CodeLookupBox)source; 
    CodeLookup code = e.NewValue as CodeLookup; 
    // this right here is the fix to the original problem: 
    if (box.CodeLookupTable == null && code != null) 
    { 
     box.CodeLookupTable = code.Table; 
    } 
    box.MainComboBox.SelectedItem = e.NewValue; 
} 

public CodeLookup SelectedCode 
{ 
    get { return GetValue(SelectedCodeProperty) as CodeLookup; } 
    set { SetValue(SelectedCodeProperty, value); } 
} 

#endregion 

#region CodeLookupTable 

public static readonly DependencyProperty CodeLookupTableProperty = DependencyProperty.Register(
    "CodeLookupTable", typeof(CodeLookupTable), typeof(CodeLookupBox), 
    new FrameworkPropertyMetadata(OnCodeLookupTablePropertyChanged)); 

private static void OnCodeLookupTablePropertyChanged(DependencyObject source, 
DependencyPropertyChangedEventArgs e) 
{ 
    CodeLookupBox box = (CodeLookupBox)source; 
    CodeLookupTable table = (CodeLookupTable)e.NewValue; 

    box.ViewSource = new CollectionViewSource { Source = table.Codes }; 
    box.View = box.ViewSource.View; 
    box.MainComboBox.ItemsSource = box.View; 

} 

public CodeLookupTable CodeLookupTable 
{ 
    get { return GetValue(CodeLookupTableProperty) as CodeLookupTable; } 
    set { SetValue(CodeLookupTableProperty, value); } 
} 

#endregion 
+0

दिलचस्प। मुझे लगता है कि 'चयनित कोड' और 'कोड लुकअप' डीपी हैं। क्या आप उनकी घोषणाएं दिखा सकते हैं और आप 'आइटमसोर्स' और 'चयनित इटैम' पर परिवर्तन कैसे पारित कर सकते हैं? –

+0

वे हैं, और निश्चित हैं; इस सवाल को संपादित करें देखें। –

0

कोशिश भी ConvertBack समारोह को लागू करने के लिए, आप दो तरह से तो समस्या बाध्यकारी उपयोग कर रहे हैं हो सकता है कि अपवाद "XAML" लेकिन जब आप डिबग मोड में कदम आप शायद "भेजें मूल्य वापस रोक द्वारा नजरअंदाज कर दिया जाएगा "-ऑपरेशन?

+0

एक अच्छा विचार, बहुत अच्छा मैंने पहले से ही यह किया है। यह कुछ भी नहीं बदला। मैंने कनवर्टबैक को 'वैल्यू' वापस करने के लिए बदल दिया और एक ही परिणाम मिला। इसके अलावा, कनवर्टर के प्रभाव के लिए मुझे डीबगर के माध्यम से कदम उठाने की ज़रूरत नहीं है। मैं एक रिलीज निर्माण चला सकता है। –

0

हम्म ... बहुत अजीब। एकाधिक कन्वर्टर्स के साथ मल्टीबिंडिंग से निपटने पर मैंने समान व्यवहार देखा है, लेकिन एक साधारण बाध्यकारी पर नहीं। जिज्ञासा से, आप अपने डीपी को नियंत्रण में कैसे परिभाषित कर रहे हैं?कुछ सामान (कॉलबैक, मेटाडाटा विकल्प, आदि सहित)

(कनवर्टर हुक हटाने के बाद) की कोशिश करना:

  • मोड चूक (यानी, TwoWay निकालने के लिए)
  • ValidatesOnDataErrors निकालें
  • चयनित कोड डीपी
0

चयनित कोड को क्या सेट करता है? क्या आप संपत्ति के लिए कोड पोस्ट कर सकते हैं हैंडलर बदल दिया?

आपने सुझाव दिया है कि डिबगिंग से पता चलता है कि संपत्ति सही मूल्य पर सेट की जा रही है, इसलिए सबसे स्पष्ट सुझाव यह है कि आपका इच्छित व्यवहार प्रदान करने वाला कोड गलत है।

संबंधित मुद्दे