2010-03-10 14 views
5

में उपयोग करने के लिए रनटाइम पर DisplayNameAttribute को कैसे बदलें, मैं सोच रहा हूं कि रनटाइम पर DisplayNameAttribute को कैसे बदला जाए, मैं चाहता हूं कि जब मैं कुछ रूपांतरण करता हूं तो मेरे प्रॉपर्टी ग्रिड में मेटर्स के बजाय डिस्प्लेनाम फीट होना चाहिए, मुमकिन?प्रॉपर्टी ग्रिड सी #

[DisplayName("Meters")] 
public double Distance 
    { 
    get{return distance;} 
    } 
+0

आप इसे हमेशा 'दूरी' पर सेट कर सकते हैं और मान में इकाइयों को शामिल कर सकते हैं, उदा। "दूरी | 34 मीटर" और "दूरी | 112 फीट"। –

+0

यदि मैं अपना प्रकार उदाहरण के लिए दोगुना हूं तो मैं यह कैसे करूं? – DogDog

उत्तर

11

यह करने के लिए अलग अलग तरीके के एक नंबर रहे हैं। सबसे सरल यह है कि कुछ I18n उत्पादों को कैसे करें - विशेषता को उपclass और पाठ को अवरुद्ध करें; लेकिन यह केवल तभी काम करता है यदि आप प्रकार के स्वामी हैं, और एक विशेषता से आप संदर्भ तक नहीं पहुंच सकते हैं।

अगले चीजों को देखने की TypeConverter होगा, के बाद से इस गुणों पर घटक मॉडल को देखने के लिए पहुँच प्रदान करता है, और यह ;-p अगले दो विकल्पों की तुलना में आसान है PropertyGrid के साथ काम करेंगे, लेकिन नहीं DataGridView आदि

अगला सूची पर ICustomTypeDescriptor है - लागू करने के लिए नहीं एक मजेदार इंटरफेस है, लेकिन आप अपने खुद के संपत्ति-डिस्क्रिप्टर में स्वैप कर सकते हैं। यह आवश्यक है कि आप इस प्रकार के मालिक हैं (इंटरफ़ेस समर्थन प्रदान करने के लिए)।

अंत में, CustomTypeDescriptor पिछले तरह है, लेकिन प्रकार आपकी नहीं है के लिए भी काम करता है, और दोनों प्रकार और वस्तु स्तर (सब कुछ केवल वस्तु का समर्थन करता है) पर मेटाडाटा बदलाव के लिए उपयोग की अनुमति देता है।

कौन सा चुनने के लिए? मुझे संदेह है कि TypeConverter सबसे समझदार होगा; आपको ऑब्जेक्ट-संदर्भ की आवश्यकता है (जो एक उप-वर्गीकृत विशेषता प्रदान नहीं करता है), लेकिन आपको अतिरिक्त जटिलता की आवश्यकता नहीं है।

यहां एक उदाहरण है; ध्यान दें कि TypeConverter कोड में हमारे पास ऑब्जेक्ट-संदर्भ तक पहुंच है। नाम सरल है, तो TypeConverter में डालने (जब संपत्ति बनाने) पर्याप्त होना चाहिए।

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Windows.Forms; 
class MyFunkyTypeConverter : ExpandableObjectConverter 
{ 
    public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 
    { 
     PropertyDescriptorCollection props = base.GetProperties(context, value, attributes); 
     List<PropertyDescriptor> list = new List<PropertyDescriptor>(props.Count); 
     foreach (PropertyDescriptor prop in props) 
     { 
      switch (prop.Name) 
      { 
       case "Distance": 
        list.Add(new DisplayNamePropertyDescriptor(
         prop, "your magic code here")); 
        break; 
       default: 
        list.Add(prop); 
        break; 
      } 
     } 
     return new PropertyDescriptorCollection(list.ToArray(), true); 
    } 
} 
class DisplayNamePropertyDescriptor : PropertyDescriptor 
{ 
    private readonly string displayName; 
    private readonly PropertyDescriptor parent; 
    public DisplayNamePropertyDescriptor(
     PropertyDescriptor parent, string displayName) : base(parent) 
    { 
     this.displayName = displayName; 
     this.parent = parent; 
    } 
    public override string DisplayName 
    {get { return displayName; } } 

    public override bool ShouldSerializeValue(object component) 
    { return parent.ShouldSerializeValue(component); } 

    public override void SetValue(object component, object value) { 
     parent.SetValue(component, value); 
    } 
    public override object GetValue(object component) 
    { 
     return parent.GetValue(component); 
    } 
    public override void ResetValue(object component) 
    { 
     parent.ResetValue(component); 
    } 
    public override bool CanResetValue(object component) 
    { 
     return parent.CanResetValue(component); 
    } 
    public override bool IsReadOnly 
    { 
     get { return parent.IsReadOnly; } 
    } 
    public override void AddValueChanged(object component, EventHandler handler) 
    { 
     parent.AddValueChanged(component, handler); 
    } 
    public override void RemoveValueChanged(object component, EventHandler handler) 
    { 
     parent.RemoveValueChanged(component, handler); 
    } 
    public override bool SupportsChangeEvents 
    { 
     get { return parent.SupportsChangeEvents; } 
    } 
    public override Type PropertyType 
    { 
     get { return parent.PropertyType; } 
    } 
    public override TypeConverter Converter 
    { 
     get { return parent.Converter; } 
    } 
    public override Type ComponentType 
    { 
     get { return parent.ComponentType; } 
    } 
    public override string Description 
    { 
     get { return parent.Description; } 
    } 
    public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) 
    { 
     return parent.GetChildProperties(instance, filter); 
    } 
    public override string Name 
    { 
     get { return parent.Name; } 
    } 

} 

[TypeConverter(typeof(MyFunkyTypeConverter))] 
class MyFunkyType 
{ 
    public double Distance {get;set;} 

    public double AnotherProperty { get; set; } 
} 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.Run(new Form { Controls = { 
      new PropertyGrid { Dock = DockStyle.Fill, 
       SelectedObject = new MyFunkyType { 
        Distance = 123.45 
       }} 
     }}); 
    } 
} 
0

विशेषताएँ प्रकार के हिस्से के रूप में संकलित की जाती हैं, इसलिए उन्हें रनटाइम पर बदला नहीं जा सकता है।

एक वैकल्पिक समाधान माप है जो आप हमेशा सब मान संग्रहीत की आंतरिक इकाई निर्धारित करने के लिए हो सकता है। मीटर एक अच्छा उम्मीदवार है। फिर "अनुवादक" सेवाएं बनाएं जो आपके उपभोक्ता वर्ग और मूल वर्ग के बीच बैठें, जो सभी मानों को एक अलग प्रारूप में परिवर्तित करने के लिए ज़िम्मेदार है।

+0

प्रतिबिंब के माध्यम से भी ऐसा नहीं कर सकता? – Nick

+0

सबसे अच्छा तुम कर सकते हो विशेषता आप चाहते हैं के साथ एक नई विधानसभा उत्पन्न करने के लिए किया जाएगा। लेकिन मुझे नहीं पता कि क्या कोई उपयोग होगा। –

+0

@ निक प्रतिबिंब "केवल पढ़ने के लिए" है - उदा। यह आपको प्रकारों के बारे में जानकारी बता सकता है, जिसमें उन्हें निष्पादित करने के लिए आवश्यक जानकारी भी शामिल है, लेकिन आप उन्हें बदल नहीं सकते हैं। जैसा कि @ नाडर बताते हैं, आप अपने इच्छित परिवर्तनों के साथ एक नई असेंबली उत्पन्न कर सकते हैं, लेकिन शायद यह किसी भी समस्या का समाधान नहीं करता है। –

0

यूनिट को डिस्प्ले नाम में सेट करना थोड़ा अजीब है, लेकिन यदि यह वास्तव में आप क्या करना चाहते हैं, तो आपका एकमात्र समाधान कस्टम प्रॉपर्टीडिस्क्रिप्टर्स के साथ अपनी संपत्तियां प्रकाशित करना है (टाइपकॉन्टर या कस्टम टाइप के लिए धन्यवाद वर्णनकर्ता) और DisplayName संपत्ति को ओवरराइड करने के लिए।

भी यहाँ उत्तर दिया: Change DisplayName attribute for a property

0

मैं अगर यह काम करेंगे पता नहीं है, लेकिन अपने DisplayName एक गुण है। प्रत्येक वर्ग और प्रत्येक वर्ग के सदस्यों के पास विशेषताएँ सेट हो सकती हैं। उस ने कहा, यह समझ में आता है कि PropertyInfo आपको इस विशेषता के लिए acces देगा। अब, अगर आप इस तरह से जाने के लिए और आने करवाते हैं PropertyInfo.GetCustomAttributes() या यह की तरह कुछ, और आप अपने गुण मान प्राप्त है, यह आप का कहना है कि केवल पढ़ने के लिए है के रूप में आप निक के लिए कहा है?

0

DisplayName विशेषता पहले से ही (इस स्थिति की तरह) मौजूद है और आप सिर्फ नाम बदलना चाहते हैं, तो आप इस संपत्ति के propertydescriptor उपयोग कर सकते हैं। विशेषताएँ प्रॉपर्टी को तब तक देखें जब तक आप विशेषता नहीं पाते और मान बदलते हैं।

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