2013-02-22 13 views
5

पर टाइप प्रकार कनवर्टर को बाध्यकारी मेरे पास निम्न परिदृश्य है: मेरे पास एक enum है, और इसे डेटाग्रिड व्यूटेक्स्टबॉक्स कॉलम पर डेटाग्रिड व्यू (डाटाबेस) में दिखाएं।एक गणना

//[TypeConverter(typeof(EnumStringConverter))] 
    public enum YesNoNA 
    { 
     [EnumDescription("Yes")] 
     Yes, 
     [EnumDescription("No")] 
     No, 
     [EnumDescription("N/A")] 
     NA 
    } 

यहाँ और एक सरल संपत्ति यह का उपयोग करता है:

यहाँ मेरी enum है

[TypeConverter(typeof(EnumStringConverter))] 
    public YesNoNA HighLimitWithinBounds { get; protected set; } 

स्थिति मैं ऊपर है में, typeconverter बस ठीक काम करता है। यह मेरे लिए रूपांतरण करता है।

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

मैंने इस कक्षा को अन्य कक्षाओं में किया है, और यह ठीक काम करता है।

एक enum पर सीधे टाइपकॉन्टर डालने क्यों काम नहीं करता है?

संदर्भ के लिए, मेरी typeconverter है:

public class EnumStringConverter : TypeConverter 
    { 
     public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object value, Type destinationType) 
     { 
     if (value != null && destinationType == typeof(string)) 
     { 
      return "Edited to protect the innocent!"; 
     } 
     return TypeDescriptor.GetConverter(typeof(Enum)).ConvertTo(context, culture, value, destinationType); 
     } 
     public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
     { 
     if (destinationType == typeof(string)) 
     { 
      return true; 
     } 
     return base.CanConvertTo(context, destinationType); 
     } 
    }; 
+1

शायद आपको यह विधि एक कोशिश देनी चाहिए: http://en.wikipedia.org/wiki/Rubber_duck_debugging – espais

+0

संभावित डुप्लिकेट [मैं सी # enums में ToString कैसे ओवरराइड कर सकता हूं?] (Http://stackoverflow.com/questions/796607/कैसे-करें-i-override-tostring-in-c-sharp-enums) –

+0

निश्चित रूप से संबंधित नहीं है। उस धागे में उत्तर का समाधान पहले से ही लागू किया गया है। यह सवाल इसे और अधिक ले रहा है। – greggorob64

उत्तर

2

मुझे यकीन है कि आप द्वारा क्या मतलब है नहीं कर रहा हूँ "यह मेरा आदर्श समाधान से अधिक जटिल है"। मेरे पास ऐसा करने का एक तरीका है जो आपके से अलग है लेकिन यह कम जटिल नहीं हो सकता है। मैं कहूंगा कि मेरे रास्ते में आगे के ऊपर की ओर बढ़ना शामिल है लेकिन आप इसे अपने आवेदन में जितना अधिक उपयोग करेंगे उतना अधिक भुगतान करेंगे। यह आपके आवेदन को स्थानीयकरण योग्य बनाने के लिए तैयार करता है और इसका मतलब है कि आपको प्रत्येक enum मान में विशेषताओं को जोड़ने की आवश्यकता नहीं है।

1) एक संसाधन प्रबंधक कैश बनाओ

इस भाग वैकल्पिक है; हालांकि यदि आप कई संसाधन फ़ाइलों का उपयोग करते हैं तो कई बार ऐसा करने से प्रदर्शन में वृद्धि हो सकती है कि कितना प्रतिबिंब किया जाता है।

using System; 
using System.Collections.Generic; 
using System.Reflection; 
using System.Resources; 

namespace AppResourceLib.Public.Reflection 
{ 
    internal static class ResourceManagerCache 
    { 
    private static Dictionary<Type, ResourceManager> _resourceManagerMap = 
     new Dictionary<Type, ResourceManager>(); 

    public static ResourceManager GetResourceManager(Type resourceType) 
    { 
     ResourceManager resourceManager = null; 

     // Make sure the type is valid. 
     if (null != resourceType) 
     { 
     // Try getting the cached resource manager. 
     if (!ResourceManagerCache._resourceManagerMap.TryGetValue(resourceType, out resourceManager)) 
     { 
      // If it is not in the cache create it. 
      resourceManager = resourceType.InvokeMember(
      "ResourceManager", 
      (BindingFlags.GetProperty | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), 
      null,             
      null,             
      null) as ResourceManager; 

      // If it was created, add the resource manager to the cache. 
      if (null != resourceManager) 
      { 
      ResourceManagerCache._resourceManagerMap.Add(resourceType, resourceManager); 
      } 
     } 
     } 

     return resourceManager; 
    } 
    } 
} 

2) एक स्थानीय विवरण गुण

बनाएं यह विशेषता है कि आप Enum प्रकार के लिए लागू होगा। इसके बारे में अच्छी बात यह है कि आपको प्रत्येक enum में एक विशेषता जोड़ने की ज़रूरत नहीं है, केवल एनम प्रकार की घोषणा से ऊपर एक बार।

using System; 
using System.ComponentModel; 

namespace AppResourceLib.Public.Reflection 
{ 
    /// <summary> 
    /// A resource type attribute that can be applied to enumerations. 
    /// </summary> 
    [AttributeUsage(AttributeTargets.Enum)] 
    public sealed class LocalizedDescriptionAttribute : Attribute 
    { 
    /// <summary> 
    /// The type of resource associated with the enum type. 
    /// </summary> 
    private Type _resourceType; 

    public LocalizedDescriptionAttribute(Type resourceType) 
    { 
     this._resourceType = resourceType; 
    } 

    /// <summary> 
    /// The type of resource associated with the enum type. 
    /// </summary> 
    public Type ResourceType 
    { 
     get 
     { 
     return this._resourceType; 
     } 
    } 
    } 
} 

3) बनाएं स्थानीयकृत विवरण कनवर्टर

इस स्ट्रिंग में enum मूल्य धर्मान्तरित आप तार संसाधन (.resx) फ़ाइल में दे देंगे।

using System; 
using System.Globalization; 
using System.Linq; 
using System.Reflection; 
using System.Resources; 
using System.Windows.Data; 

namespace AppResourceLib.Public.Reflection 
{ 
    [ValueConversion(typeof(Object), typeof(String))] 
    public class LocalizedDescriptionConverter : IValueConverter 
    { 
    public Object Convert(Object value, Type targetType, Object param, CultureInfo cultureInfo) 
    { 
     String description = null; 

     if (null != value) 
     { 
     // If everything fails then at least return the value.ToString(). 
     description = value.ToString(); 

     // Get the LocalizedDescriptionAttribute of the object. 
     LocalizedDescriptionAttribute attribute = 
      value.GetType().GetCustomAttribute(typeof(LocalizedDescriptionAttribute)) 
      as LocalizedDescriptionAttribute; 

     // Make sure we found a LocalizedDescriptionAttribute. 
     if (null != attribute) 
     {   
      ResourceManager resourceManager = 
      ResourceManagerCache.GetResourceManager(attribute.ResourceType); 

      if (null != resourceManager) 
      { 
      // Use the ResourceManager to get the description you gave the object value. 
      // Here we just use the object value.ToString() (the name of the object) to get 
      // the string in the .resx file. The only constraint here is that you have to 
      // name your object description strings in the .resx file the same as your objects. 
      // The benefit is that you only have to declare the LocalizedDescriptionAttribute 
      // above the object type, not an attribute over every object. 
      // And this way is localizable. 
      description = resourceManager.GetString(value.ToString(), cultureInfo); 

      String formatString = (param as String); 

      // If a format string was passed in as a parameter, 
      // make a string out of that. 
      if (!String.IsNullOrEmpty(formatString)) 
      { 
       formatString = formatString.Replace("\\t", "\t"); 
       formatString = formatString.Replace("\\n", "\n"); 
       formatString = formatString.Replace("\\r", "\r"); 

       description = String.Format(formatString, value.ToString(), description);    
      }   
      } 
     } 
     } 

     return description;  
    } 

    public Object ConvertBack(Object value, Type targetType, Object param, CultureInfo cultureInfo) 
    { 
     throw new NotImplementedException(); 

     return null; 
     } 
    } 
} 

4) एक संसाधन बनाएं (.resx) स्ट्रिंग फ़ाइल

अब आप एक संसाधन फ़ाइल है कि आप अपने विवरण Enums कुंजी मान शैली के लिए चाहते हैं शामिल होंगे बनाना चाहते हैं। इसका मतलब यह है कि स्ट्रिंग संसाधनों के "नाम" कॉलम में आप व्यक्तिगत enums का सटीक नाम डाल देंगे और "मान" कॉलम में आप उस स्ट्रिंग को डाल देंगे जिसे आप उस enum को परिवर्तित करते समय प्राप्त करना चाहते हैं।
उदाहरण के लिए, कहें कि आपके पास निम्नलिखित एम्स हैं।

public enum MyColors 
{ 
    Black, 
    Blue, 
    White 
} 

फिर अपने स्ट्रिंग संसाधन फ़ाइल इस प्रकार दिखाई देगा ...

नाम | मूल्य

काला | एक डार्क रंग
नीला | एक शांत रंग
व्हाइट | एक चमकीला रंग

5) गुण

साथ Enums बनाएं अब हम अंत में LocalizedDescription साथ Enum घोषणा करते हैं। आपके द्वारा LocalizedDescription विशेषता में पारित पैरामीटर आपकी स्ट्रिंग संसाधन फ़ाइल का प्रकार है। अब जब कनवर्टर का उपयोग किया जाता है तो यह enum प्रकार की विशेषता दिखाई देगा, संसाधन फ़ाइल प्राप्त करें, उस कुंजी स्ट्रिंग को देखें जो विशेष enum मान के स्ट्रिंग मान से मेल खाता है, और संसाधन फ़ाइल से मान को परिवर्तित स्ट्रिंग के रूप में वापस कर देता है।

using AppResourceLib.Public; 
using AppResourceLib.Public.Reflection; 

namespace MyEnums 
{ 
    [LocalizedDescription(typeof(MyColorStrings))] 
    public enum MyColors 
    { 
    Black, 
    Blue, 
    White 
    } 
} 

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

अपने xaml कोड में आप अपने UI तत्व में enums के मान प्राप्त करने के लिए डेटा प्रदाता बनाना चाहते हैं (मैं यहां एक कॉम्बोबॉक्स का उपयोग कर रहा हूं ...)। फिर आप कनवर्टर को एनम कनवर्टर का उपयोग करने के लिए अपने यूआई तत्व को उपलब्ध और टेम्पलेट बनाना चाहते हैं। तो यहां यह जाता है ...

 <!-- Enum Colors --> 
    <ObjectDataProvider x:Key="MyColorEnums" 
         MethodName="GetValues" 
         ObjectType="{x:Type sys:Enum}"> 
    <ObjectDataProvider.MethodParameters> 
     <x:Type TypeName="MyColors"/> 
    </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 


    <!-- Enum Type Converter --> 
    <LocalizedDescriptionConverter x:Key="EnumConverter"/> 


    <!-- Dropdown Expand ComboBox Template --> 
    <DataTemplate x:Key="MyColorsComboBoxTemplate"> 
    <Label Content="{Binding Path=., Mode=OneWay, 
     Converter={StaticResource EnumConverter}}" 
      Height="Auto" Margin="0" VerticalAlignment="Center"/> 
    </DataTemplate> 

    <!-- And finally the ComboBox that will display all of your enum values 
    but will use the strings from the resource file instead of enum.ToString() --> 
    <ComboBox Width="80" HorizontalAlignment="Left" 
    ItemTemplate="{StaticResource MyColorsComboBoxTemplate}" 
    ItemsSource="{Binding Source={StaticResource MyColorEnums}}"> 

वाह, क्षमा करें यह बहुत लंबा है। मुझे यकीन नहीं है कि यह आपके लिए बहुत जटिल है लेकिन यह एक और विकल्प है। आशा करता हूँ की ये काम करेगा!

+1

मेरा उदाहरण आपके जैसा ही है (आप एक संसाधन फ़ाइल का उपयोग करने में एक कदम आगे जाते हैं, जिसे मैं अन्य स्थानों में उपयोग करता हूं और साथ ही बहुभाषी समर्थन प्राप्त करता हूं)। जटिलता में अंतर जो मैं उल्लेख करता हूं वह यह है कि मेरे उदाहरण के लिए enum पर बजाय * econconverter * संपत्ति पर * की आवश्यकता होती है। और दुर्भाग्यवश, मुझे नहीं लगता कि हमारे उदाहरण मिलेंगे। आप xaml का उपयोग कर रहे हैं, और मैं शुद्ध .net Winforms का उपयोग कर रहा हूँ। आप अपना combobox ले रहे हैं। आपका xaml विशेष रूप से आपके द्वारा आवश्यक कनवर्टर को कम्बोबॉक्स बाध्यकारी है, जो मैं बचने की कोशिश कर रहा हूं (मुझे नहीं लगता कि मैं सफल रहूंगा)। उत्तर के लिए धन्यवाद! – greggorob64

+0

ओह, मैं देखता हूं कि आपका क्या मतलब है। क्षमा करें मैं मदद नहीं कर सका। – akagixxer

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