2012-10-18 7 views
5

मैं अपने कुछ वर्गों के बीच डेटा बाइंडिंग का उपयोग करना चाहता हूं। दूसरे शब्दों में, मैं एक मॉडल वर्ग और यूआई के बीच मूल्यों को बाध्य नहीं कर रहा हूं, लेकिन विभिन्न वर्गों के बीच चर को बांधने के लिए।मैं सी # के साथ कोड में डेटा बाध्यकारी कैसे कर सकता हूं?

मैंने कई स्थानों पर सी # में डेटा बाध्यकारी के बारे में पढ़ा है, लेकिन उनमें से अधिकांश विंडोज फॉर्म और स्रोत ऑब्जेक्ट के बीच बाध्यकारी का जिक्र कर रहे हैं।

मैं अभी भी सी # के लिए नया हूं। इस तरह मैं समझता हूं कि मुझे क्या करना चाहिए:

सबसे पहले, मेरे स्रोत ऑब्जेक्ट के लिए, का कहना है कि DataObject का वर्ग नाम है। स्रोत ऑब्जेक्ट को INotifyPropertyChange इंटरफ़ेस को कार्यान्वित करना है, और तब ईवेंट को ट्रिगर करें जब भी संपत्ति, health, बदलने के लिए सेट है। मुझे इस बात से कोई समस्या नहीं है।

अब मान लीजिए कि मेरे पास लक्ष्य ऑब्जेक्ट है जिसे CharacterClass कहा जाता है। lifeCharacterClass में एक संपत्ति है, और लक्ष्य संपत्ति है कि मैं स्रोत ऑब्जेक्ट की health संपत्ति से जुड़ना चाहता हूं।

मैं कोड में केवल दो सामान्य गुणों के साथ दो गुणों को एक साथ जोड़ सकता हूं (दोनों तरफा और दो-तरफा) कैसे?

कारण है कि मैं इस प्रश्न को पूछने पर पृष्ठभूमि जानकारी का एक बिट:

शायद ज़रुरत पड़े आपको लगता है कि यह एक डुप्लिकेट किए गए सवाल यह है कि, यह नहीं है। मैंने एसई के माध्यम से खोज की है। कोड में डाटाबेसिंग पर अन्य प्रश्न WPF या XAML के संदर्भ में हैं, जो मेरे लिए नहीं है। मैंने एमएसडीएन पर कई लेख भी पढ़े हैं और ऐसा लगता है कि मैं Binding ऑब्जेक्ट बना सकता हूं, और फिर स्रोत और लक्ष्य को BindingOperations.SetBinding() के माध्यम से बांध सकता हूं। हालांकि, Binding वर्ग System.Windows.Data.Binding के नामस्थान के तहत WPF लाइब्रेरी का हिस्सा प्रतीत होता है। हालांकि मैं सी # का उपयोग कर रहा हूं, मुझे संदेह है कि मेरे पास डब्ल्यूपीएफ लाइब्रेरी तक पहुंचने के लिए लक्जरी होगा क्योंकि मैं मुख्य रूप से सी # को यूनिटी 3 डी के भीतर केवल एक स्क्रिप्टिंग भाषा के रूप में उपयोग कर रहा हूं। मेरा मानना ​​है कि मुझे केवल वेनिला नेट फ्रेमवर्क तक पहुंच है। लेकिन, मुझे इस बारे में बहुत यकीन नहीं है क्योंकि मैं अभी भी सी # के लिए नया हूं।

उत्तर

7

हालांकि बाइंडिंग के लिए बहुत सारे समर्थन हैं जो यूआई ढांचे के साथ कसकर मिलकर उपयोग किए जाते हैं, फिर भी आप आसानी से अपने बाध्यकारी ढांचे को लिख सकते हैं।

यहां एक पीओसी है जो दो वस्तुओं के गुणों के बीच एक तरफा बाध्यकारी लागू करता है।

नोट: यह संभवतः एक संभावित पीओसी है (उच्च प्रदर्शन/उत्पादन परिदृश्य के लिए ठीक-ट्यूनिंग की आवश्यकता हो सकती है) और .NET 2.0 कक्षाओं और इंटरफेस का उपयोग किसी भी यूआई फ्रेमवर्क पर निर्भरता के साथ करता है (' अपने शब्दों में वेनिला 'नेट फ्रेमवर्क :))।एक बार जब आप इस तरह समझ गए हैं, आप आसानी से 2 तरह के रूप में अच्छी

class Program 
{ 
    public static void Main() 
    { 
     Source src = new Source(); 
     Destination dst = new Destination(src); 
     dst.Name = "Destination"; 
     dst.MyValue = -100; 
     src.Value = 50; //changes MyValue as well 
     src.Value = 45; //changes MyValue as well 
     Console.ReadLine(); 
    } 
} 

//A way to provide source property to destination property 
//mapping to the binding engine. Any other way can be used as well 
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
internal class BindToAttribute : Attribute 
{ 
    public string PropertyName 
    { 
     get; 
     private set; 
    } 

    //Allows binding of different properties to different sources 
    public int SourceId 
    { 
     get; 
     private set; 
    } 

    public BindToAttribute(string propertyName, int sourceId) 
    { 
     PropertyName = propertyName; 
     SourceId = sourceId; 
    } 
} 

//INotifyPropertyChanged, so that binding engine knows when source gets updated 
internal class Source : INotifyPropertyChanged 
{ 
    private int _value; 
    public int Value 
    { 
     get 
     { 
      return _value; 
     } 
     set 
     { 
      if (_value != value) 
      { 
       _value = value; 
       Console.WriteLine("Value is now: " + _value); 
       OnPropertyChanged("Value"); 
      } 
     } 
    } 

    void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

internal class Destination 
{ 
    private BindingEngine<Destination> _binder; 

    private int _myValue; 

    [BindTo("Value", 1)] 
    public int MyValue 
    { 
     get 
     { 
      return _myValue; 
     } 
     set 
     { 
      _myValue = value; 
      Console.WriteLine("My Value is now: " + _myValue); 
     } 
    } 

    //No mapping defined for this property, hence it is not bound 
    private string _name; 
    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      _name = value; 
      Console.WriteLine("Name is now: " + _name); 
     } 
    } 

    public Destination(Source src) 
    { 
     //Binder for Source no 1 
     _binder = new BindingEngine<Destination>(this, src, 1); 
    } 
} 

internal class BindingEngine<T> 
{ 
    private readonly T _destination; 
    private readonly PropertyDescriptorCollection _sourceProperties; 
    private readonly Dictionary<string, PropertyDescriptor> _srcToDestMapping; 

    public BindingEngine(T destination, INotifyPropertyChanged source, int srcId) 
    { 
     _destination = destination; 

     //Get a list of destination properties 
     PropertyDescriptorCollection destinationProperties = TypeDescriptor.GetProperties(destination); 

     //Get a list of source properties 
     _sourceProperties = TypeDescriptor.GetProperties(source); 

     //This is the source property to destination property mapping 
     _srcToDestMapping = new Dictionary<string, PropertyDescriptor>(); 

     //listen for INotifyPropertyChanged event on the source 
     source.PropertyChanged += SourcePropertyChanged; 

     foreach (PropertyDescriptor property in destinationProperties) 
     { 
      //Prepare the mapping. 
      //Add those properties for which binding has been defined 
      var attribute = (BindToAttribute)property.Attributes[typeof(BindToAttribute)]; 
      if (attribute != null && attribute.SourceId == srcId) 
      { 
       _srcToDestMapping[attribute.PropertyName] = property; 
      } 
     } 
    } 

    void SourcePropertyChanged(object sender, PropertyChangedEventArgs args) 
    { 
     if (_srcToDestMapping.ContainsKey(args.PropertyName)) 
     { 
      //Get the destination property from mapping and update it 
      _srcToDestMapping[args.PropertyName].SetValue(_destination, _sourceProperties[args.PropertyName].GetValue(sender)); 
     } 
    } 
} 

enter image description here

0

मेरा मानना ​​है कि मैं केवल वेनिला नेट ढांचे

वास्तविकता बंधन है कि डेटा यूआई में इस्तेमाल किया जाता है की पहुंच है। इसलिए, यदि कोई डेटा बाध्यकारी के बारे में बात करता है, तो वह स्वचालित रूप से "यूआई फ्रेमवर्क नाम] में डेटा बाध्यकारी" का तात्पर्य है।

आप डेटा बाध्यकारी के बजाय ऑब्जेक्ट-टू-ऑब्जेक्ट मैपिंग पर विचार कर सकते हैं।

+0

असल में, हाँ, आप यूआई के लिए बाध्यकारी जा रहा है डेटा के बारे में सही हो बाध्यकारी समर्थन करने के लिए इस विस्तार कर सकते हैं। मेरी स्थिति में, मैं एक यूआई बना रहा हूं, लेकिन विंडोज़ फॉर्म के साथ नहीं। और उन सभी * लक्षित वस्तुओं * मैं मुख्य रूप से मेरे यूआई कक्षाओं का जिक्र कर रहा था। तो मैं उम्मीद कर रहा हूं कि सॉर्ट डेटा बाध्यकारी तकनीक के "कस्टम" के लिए मैं अपने स्वयं के गैर-विनफॉर्म यूआई पर लागू कर सकता हूं। – Carven

+0

@xEnOn: मुख्य समस्या यह है कि बाध्यकारी इंजन कड़ाई से यूआई फ्रेमवर्क आंतरिक के साथ मिलकर हैं। उदाहरण के लिए, डब्ल्यूपीएफ बाध्यकारी निर्भरता गुणों का उपयोग करता है, इसलिए, यदि आप इसका उपयोग करना चाहते हैं, तो आपको 'यूपीएंडेंसी ऑब्जेक्ट' वंशज होने के लिए अपनी यूआई कक्षाएं लिखनी होंगी। मुझे लगता है, आपको अपना बाध्यकारी इंजन लिखना चाहिए। – Dennis

+0

मैं देखता हूं। धन्यवाद! ऐसा लगता है कि मेरे पास सी # के मौजूदा डेटा बाध्यकारी इंजन का उपयोग करने के लिए कोई भाग्य नहीं है। :(मान लीजिए कि मुझे अपना खुद का बाध्यकारी इंजन कैसे लिख सकता है। शायद मैं यह समझने के लिए एक नया प्रश्न दूंगा कि डेटा बाध्यकारी इंजन हुड के नीचे कैसे काम करते हैं, ताकि मुझे यह पता चल सके कि मैं डेटा बाइंडिंग कैसे लिख सकता हूं इंजन। बहुत बहुत धन्यवाद, डेनिस। :) – Carven

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

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