2015-09-23 3 views
7

का उपयोग करके विकल्पों में स्टोर सरणी मान लीजिए कि मुझे टेम्पलेट से ताज़ा रूप से बनाए गए एक्सटेंशन में किसी भी सरणी को स्टोर करने की आवश्यकता है।डायलॉगपेज

मैं सिर्फ नए VSIX प्रोजेक्ट बनाया, VSPackage से जोड़ रहे है, तो जोड़ा विकल्प पेज ग्रिड (DialogPage)। तब मैं एक ऐसी ही प्रश्न के उत्तरों के निर्देशों का पालन किया: DialogPage - string array not persisted.

और, प्रदर्शन के उद्देश्य से, चलो भी कस्टम प्रकार कनवर्टर साथ int[] सरणी और सादे int जोड़ते हैं।

// [standard attributes] 
[ProvideOptionPage(typeof(OptionPageGrid), 
"My Category", "My Grid Page", 0, 0, true)] 
public sealed class FooBarVSPackage : Package 
{ 
    // standard code 
} 

public class OptionPageGrid : DialogPage 
{ 
    // [typical attributes] 
    [TypeConverter(typeof(StringArrayConverter))] 
    public string[] Foos 
    { get; set; } 

    // [typical attributes] 
    [TypeConverter(typeof(CustomIntConverter))] 
    public int Bar 
    { get; set; } 

    // [typical attributes] 
    [TypeConverter(typeof(IntArrayConverter))] 
    public int[] Bazes 
    { get; set; } 
} 

class StringArrayConverter : TypeConverter 
{ 
    // exact copy of code from similar question/answer mentioned above 
} 

public class IntArrayConverter : TypeConverter 
{ 
    private const string delimiter = "#@#"; 

    // CanConvertFrom, ConvertTo, etc. overridden in similar fashion 
} 

public class CustomIntConverter : TypeConverter 
{ 
    // CanConvertFrom() overridden 
    // CanConvertTo() overridden 

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) 
    { 
     var v = value as string; 
     return int.Parse(v.TrimStart('*')); 
    } 

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) 
    { 
     var v = (int)value; 
     return v.ToString().PadLeft(25, '*'); 
    } 
} 

जब मैं उन विकल्पों को संपादित, मैं देख सकता हूँ कि कनवर्टर वास्तव में काम करता है: Type Converter really works

लेकिन उसके बाद मैं इसे फिर से खोलना, मूल्यों के दो चला गया! केवल सादे int कायम: कैसे और कब TypeConverter तरीकों कहा जाता है: Array values are lost, but plain int persisted

भी एक अजीब चीज नहीं है। CanConvertTo()पूरे सत्र के दौरान कभी भी नहीं कहा जाता है। CanConvertFrom() और ConvertTo() को अपेक्षित फैशन में अक्सर और अधिक या कम कहा जाता है। और ConvertFrom() को कहा जाता है केवल जब विकल्प का स्ट्रिंग प्रस्तुति सीधे संपादित किया जाता है, यानी लोडिंग/बचत विकल्पों में भाग नहीं लेता है!

मुझे यकीन है कि नहीं कर रहा हूँ, लेकिन यह int विकल्प की तरह एक सा int के रूप में जमा है और केवल विकल्प जीयूआई में string में से/कर दिया है लगता है, जबकि सरणी विकल्प सिर्फ चुपचाप भी ऐसा ही करने की कोशिश कर असफल।

पुनश्च: FooBarVSIXProject

उत्तर

7

टूट "का उपयोग करने के लिए आसान" ठीक करने की कोशिश में कई घंटे बिताने के तंत्र के बाद: आप सीधे उदाहरण व्यक्तिगत रूप से साथ खेलने के लिए चाहते हैं, तो यहाँ सवाल में उदाहरण परियोजना के साथ एक GitHub रेपो है (या तो खुद टूट गया है या इसके प्रलेखन), मुझे एहसास हुआ कि समय बर्बाद करने के बजाय, मुझे केवल एक अमूर्त परत नीचे उतरनी चाहिए और ठीक वही करना चाहिए जो मैं चाहता था DialogPage तंत्र स्वचालित रूप से कार्य करता है।

एक उम्मीद होती है कि DialogPage सहेजना चाहिए/User Settings Store (या ऐसा ही कुछ) से/में स्ट्रिंग प्रतिनिधित्व (प्रकार कनवर्टर के माध्यम से प्राप्त) लोड जब इसकी SaveSettingsToStorage() और LoadSettingsFromStorage() कहा जाता है। चूंकि यह ऐसा करने के लिए मना कर दिया और उन तरीकों virtual हैं, हम वास्तव में क्या कर सकते हैं कि अपने आप को:

public class OptionPageGrid : DialogPage 
{ 
    const string collectionName = "FooBarVSIX"; 

    [Category("General")] 
    [DisplayName("Foos")] 
    [Description("Bla Foo Bla")] 
    // note that TypeConverter attribute is removed, 
    // because it's not relevant anymore 
    public string[] Foos 
    { get; set; } 

    // Bar and Bazes properties missed out to make this example shorter 

    public override void SaveSettingsToStorage() 
    { 
     base.SaveSettingsToStorage(); 

     var settingsManager = new ShellSettingsManager(ServiceProvider.GlobalProvider); 
     var userSettingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); 

     if (!userSettingsStore.CollectionExists(collectionName)) 
      userSettingsStore.CreateCollection(collectionName); 

     var converter = new StringArrayConverter(); 
     userSettingsStore.SetString(
      collectionName, 
      nameof(Foos), 
      converter.ConvertTo(this.Foos, typeof(string)) as string); 
     // save Bazes in similar way 
    } 

    public override void LoadSettingsFromStorage() 
    { 
     base.LoadSettingsFromStorage(); 

     var settingsManager = new ShellSettingsManager(ServiceProvider.GlobalProvider); 
     var userSettingsStore = settingsManager.GetWritableSettingsStore(SettingsScope.UserSettings); 

     if (!userSettingsStore.PropertyExists(collectionName, nameof(Foos))) 
      return; 

     var converter = new StringArrayConverter(); 
     this.Foos = converter.ConvertFrom(
      userSettingsStore.GetString(collectionName, nameof(Foos))) as string[]; 
     // load Bazes in similar way 
    } 
} 

अब, ज़ाहिर है, अगर आप इसे इस तरह से करते हैं, आप लिख सकते हैं और उपयोग की जरूरत नहीं है वास्तव में TypeConverter। आप केवल उन तरीकों, या कहीं भी क्रमबद्ध तर्क तर्क एम्बेड कर सकते हैं।

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

+2

यह वीएस 2015 में एक बग है। एमएस ने वीओएस 2013 और वीएस 2015 के बीच डायलॉगपेज। लोडसेटिंग फ्रॉम स्टोरेज और सेवसेटिंग्स स्टोरेज में तर्क को काफी हद तक बदल दिया है, और वे TypeSonverters का उपयोग करने वाले गुणों के लिए LoadSettingsFromStorage तोड़ दिया। मैंने वीएस 2015 की "समस्या की रिपोर्ट करें" संवाद और कनेक्ट के माध्यम से इसकी सूचना दी है, इसलिए शायद वे इसे ठीक कर देंगे। इस बीच, मुझे इसे आपके जैसे ओवरराइड के साथ काम करना पड़ा। नोट: TypeConverters अभी भी PropertyGrid में मानों को संपादित करने के लिए उपयोगी हैं। इसके अलावा, एमएस बग DialogPage.SetPropertyValue में है, जो अभी कन्वर्ट कहता है। चेंज टाइप अब। –