2015-09-23 7 views
7

テンプレートから新しく作成した拡張モジュールに配列を格納する必要があるとします。DialogPageを使用してオプションで配列を格納する

私はちょうど新しいVSIXプロジェクトを作成し、それにVSPackageを追加し、その後、オプションページグリッドDialogPage)を追加しました。それから私は、同様の質問への回答からの指示に続く:DialogPage - string array not persisted.

をそして、デモの目的のために、のは、カスタム型コンバータint[]アレイと平野intを追加してみましょう。 Type Converter really works

をしかし、私はそれを再び開いた後、値の2がなくなっ:

// [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, '*'); 
    } 
} 

私はそれらのオプションを編集するとき、私は、コンバータが実際に動作することを確認することができます!唯一の平野intは持続:いつ、どのようにTypeConverterメソッドが呼び出されます。また、1奇妙なことがあり Array values are lost, but plain int persisted

。​​はであり、決してはセッション全体で呼び出されません。 CanConvertFrom()およびConvertTo()は、多くの場合、予想される方法で多かれ少なかれ呼び出されます。 となります。はオプションの文字列表記を直接編集すると、はオプションの読み込み/保存にまったく参加しません。

私はわからないんだけど、それはintオプションのようなビットがintとして保存され、配列オプションはただ黙って同じことをやろうと失敗しながら、唯一のオプションのGUIにstringへ/からなって感じています。

PS:あなたが直接個人的に例を挙げて再生したい場合は、ここで問題になっているサンプルプロジェクトでGitHubのレポです:FooBarVSIXProject

答えて

7

「使いやすい」壊れて修正しようと数時間を過ごした後メカニズム(それ自体が壊れているか、そのドキュメンテーションか)、時間を無駄にするのではなく、ただ1つの抽象レイヤーを下ろして、私が望むものを正確に行うべきであることに気が付いたDialogPageメカニズムは自動的に行います。

一つは、そのSaveSettingsToStorage()LoadSettingsFromStorage()が呼び出されたときDialogPageUser Settings Store(またはそのような何か)から/へ(型コンバータを介して取得した)文字列表現をロード/セーブする必要があることが予想されます。それはそうすることを拒否し、これらのメソッドは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

これはVS 2015のバグです.MSはDialogPage.LoadSettingsFromStorageとSaveSettingsToStorageのロジックをVS 2013とVS 2015の間で大幅に変更し、TypeConvertersを使用するプロパティのLoadSettingsFromStorageを壊しました。私はこれをVS 2015の「問題を報告する」ダイアログとConnectを介して報告しました。最終的には問題を解決するかもしれません。その間、私はあなたのようにオーバーライドで回避策を講じなければなりませんでした。注:TypeConvertersは、PropertyGridで値を編集する場合にも有効です。また、MSバグはDialogPage.SetPropertyValueにあり、Convert.ChangeTypeを呼び出すだけです。 –

関連する問題