2009-02-02 7 views
82

आप इस परिदृश्य में WPF में ऑब्जेक्ट विधि से कैसे जुड़ते हैं?डब्ल्यूपीएफ में एक विधि से बांधें?

public class RootObject 
{ 
    public string Name { get; } 

    public ObservableCollection<ChildObject> GetChildren() {...} 
} 

public class ChildObject 
{ 
    public string Name { get; } 
} 

XAML:

<TreeView ItemsSource="some list of RootObjects"> 
    <TreeView.Resources> 
     <HierarchicalDataTemplate DataType="{x:Type data:RootObject}" 
            ItemsSource="???"> 
      <TextBlock Text="{Binding Path=Name}" /> 
     </HierarchicalDataTemplate> 
     <HierarchicalDataTemplate DataType="{x:Type data:ChildObject}"> 
      <TextBlock Text="{Binding Path=Name}" /> 
     </HierarchicalDataTemplate> 
    </TreeView.Resources> 
</TreeView> 

यहाँ मैं पेड़ से प्रत्येक RootObject पर GetChildren विधि से आबद्ध करना चाहते हैं।

संपादित एक ObjectDataProvider लिए बाइंडिंग काम करने के लिए है क्योंकि मैं ObjectDataProvider जरूरतों मदों की एक सूची है, और या तो एक स्थिर विधि के लिए बाध्य कर रहा हूँ नहीं लगता है, या यह खुद उदाहरण है और उस का उपयोग करता है बनाता है।

उदाहरण के लिए, मैट के जवाब का उपयोग कर रहा है:

System.Windows.Data Error: 33 : ObjectDataProvider cannot create object; Type='RootObject'; Error='Wrong parameters for constructor.'

System.Windows.Data Error: 34 : ObjectDataProvider: Failure trying to invoke method on type; Method='GetChildren'; Type='RootObject'; Error='The specified member cannot be invoked on target.' TargetException:'System.Reflection.TargetException: Non-static method requires a target.

+0

हाँ, आप सही हैं। ऑब्जेक्टडाटाप्रोवाइडर में ऑब्जेक्ट इंस्टेंस संपत्ति है (एक विशिष्ट उदाहरण पर इसकी विधि को कॉल करने के लिए) लेकिन मुझे नहीं लगता कि यह एक निर्भरता संपत्ति है, इसलिए आप इसे बाध्य नहीं कर सकते (AFAIK)। –

+1

हाँ मैंने ऑब्जेक्ट इंस्टेंस को बांधने की कोशिश की और पाया कि यह एक निर्भरता संपत्ति नहीं है। –

+0

मैं आपका उत्तर कुछ संदर्भ देने के लिए वैसे भी अपना उत्तर छोड़ दूंगा और किसी और की मदद करने के लिए जो इस प्रश्न को एक समान समस्या के साथ पाता है। –

उत्तर

22
नहीं

यकीन है कि कितनी अच्छी तरह यह अपने परिदृश्य में काम करेंगे, लेकिन आप इसे एक विशिष्ट विधि कॉल करने के लिए ObjectDataProvider पर MethodName संपत्ति का उपयोग कर सकते (विशिष्ट साथ पैरामीटर यदि आप विधि पैरामीटर गुण) अपने डेटा को पुनर्प्राप्त करने के लिए।

यहाँ एक टुकड़ा MSDN पृष्ठ से सीधे लिया है:

<Window.Resources> 
    <ObjectDataProvider ObjectType="{x:Type local:TemperatureScale}" 
     MethodName="ConvertTemp" x:Key="convertTemp"> 
     <ObjectDataProvider.MethodParameters> 
      <system:Double>0</system:Double> 
      <local:TempType>Celsius</local:TempType> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 
</Window.Resources> 

ताकि एक ObjectDataProvider है कि एक "TemperatureScale" वर्ग का एक उदाहरण पर एक "ConvertTemp" विधि कॉल कर रहा है है, दो पैरामीटर (0 और TempType.Celsius) गुजर ।

+0

मैंने आपके उत्तर के आधार पर अपना उत्तर अपडेट किया है। –

9

क्या आपको इस विधि से जुड़ना है?

क्या आप ऐसी संपत्ति से जुड़ सकते हैं जो गेटटर विधि है?

public ObservableCollection<ChildObject> Children 
{ 
    get 
    { 
     return GetChildren(); 
    } 
} 
+0

मुझे एक विधि से बांधना है। –

+2

मैं कैमरून की टिप्पणी का मतलब यह कहता हूं कि वह एक प्रकार के लिए बाध्यकारी है कि वह संपत्ति नहीं जोड़ सकता है। –

+1

आपको उन गुणों के लिए बाध्यकारी से बचना चाहिए जो विधि esp को कॉल करते हैं यदि विधि संभावित रूप से लंबे समय तक चल सकती है। इस तरह के तरीकों के साथ यह गुण अच्छा डिजाइन नहीं है क्योंकि कोड के उपभोक्ता को एक संपत्ति को केवल स्थानीय चर तक पहुंचने की उम्मीद है। – markmnl

4

जब तक आप एक संपत्ति विधि कॉल करने के लिए जोड़ (या एक आवरण वर्ग कि है कि संपत्ति कहते हैं बनाने के) एक ही रास्ता मैं जानता हूँ कि की एक ValueConverter उपयोग कर रहा है कर सकते हैं।

3

ObjectDataProvider भी एक ObjectInstance संपत्ति है कि ObjectType

के बजाय
3

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

ICustomTypeDescriptor और TypeDescriptionProvider प्रकार आपको जो भी चाहिए वो हासिल करने की अनुमति दे सकते हैं। this article के अनुसार:

TypeDescriptionProvider allows you to write a separate class that implements ICustomTypeDescriptor and then to register this class as the provider of descriptions for other types.

मैं इस अपने आप दृष्टिकोण प्रयास नहीं किया है, लेकिन मुझे आशा है कि यह आपके मामले में उपयोगी है।

59

एक और दृष्टिकोण आप के लिए काम कर सकते हैं, एक कस्टम IValueConverter कि एक पैरामीटर के रूप में एक विधि नाम लेता है बनाने के लिए है कि इतना है कि यह इस तरह इस्तेमाल किया जाएगा:

ItemsSource="{Binding 
    Converter={StaticResource MethodToValueConverter}, 
    ConverterParameter='GetChildren'}" 

इस कनवर्टर खोजने के लिए और विधि आह्वान होगा प्रतिबिंब का उपयोग कर। इस विधि के लिए कोई तर्क नहीं है।

public sealed class MethodToValueConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var methodName = parameter as string; 
     if (value==null || methodName==null) 
      return value; 
     var methodInfo = value.GetType().GetMethod(methodName, new Type[0]); 
     if (methodInfo==null) 
      return value; 
     return methodInfo.Invoke(value, new object[0]); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException("MethodToValueConverter can only be used for one way conversion."); 
    } 
} 

और एक इसी इकाई परीक्षण:

[Test] 
public void Convert() 
{ 
    var converter = new MethodToValueConverter(); 
    Assert.AreEqual("1234", converter.Convert(1234, typeof(string), "ToString", null)); 
    Assert.AreEqual("ABCD", converter.Convert(" ABCD ", typeof(string), "Trim", null)); 

    Assert.IsNull(converter.Convert(null, typeof(string), "ToString", null)); 

    Assert.AreEqual("Pineapple", converter.Convert("Pineapple", typeof(string), "InvalidMethodName", null)); 
} 

ध्यान दें कि यह कनवर्टर targetType पैरामीटर लागू नहीं करता है

यहां इस तरह के एक कनवर्टर के स्रोत का एक उदाहरण है।

+4

हम्म, ... एक हैक की तरह लगता है लेकिन मुझे लगता है कि यह एकमात्र तरीका हो सकता है। यह बेहद निश्चित है कि सबसे आसान होगा! – Stimul8d

0

अपने डब्ल्यूपीएफ परिदृश्य में किसी ऑब्जेक्ट की विधि से जुड़ने के लिए, आप एक ऐसी संपत्ति से जुड़ सकते हैं जो प्रतिनिधि को लौटाता है।

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