DOBON.NETプログラミング道掲示板

■34533 / 親記事)  デザイナのプロパティウィンドウで静的プロパティを選択したい
  
□投稿者/ masa 一般人(1回)-(2020/09/15(Tue) 22:14:50)
  • アイコン環境/言語:[Windows 10 64bit, C# WinForms, .NET Framework 4.7.2] 
    分類:[.NET] 

    2020/09/15(Tue) 22:16:46 編集(投稿者)

    久しぶりに投稿させていただきます。

    C#のWinFormsアプリケーションでカスタムコントロールを作成しています。
    デザイナのプロパティウィンドウにおいて、クラス型プロパティの設定値を
    自作クラスの静的プロパティの中から選択・ソースに反映させたいです。

    イメージとしてはColorプロパティでシステムのControlを選択すると、
    ソースにSystem.Drawing.SystemColors.Control;と反映されるのを実現させたいです。

    以下は例として、カスタムコントロールのForeColorを自作クラスの静的プロパティから選択させるサンプルです。
    このままだと、ソースにはSystem.Drawing.Color.FromArgb(((int)(((byte)(254)))), ((int)(((byte)(254)))), ((int)(((byte)(254)))));のように反映されてしまうため、
    MyLabelColors.MyWhite;のように反映されるようにしたいです。
    上手く言葉で説明できず恐縮ですが、どなたか解決策をご教示いただけますと幸いです。

    public class MyLabel : Label
    {
    [Editor(typeof(MyLabelTypeEditor), typeof(UITypeEditor))]
    public override Color ForeColor { get => base.ForeColor; set => base.ForeColor = value; }
    }

    public class MyLabelTypeEditor : UITypeEditor
    {
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) => UITypeEditorEditStyle.DropDown;

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
    IWindowsFormsEditorService editorService = null;
    if (provider != null) editorService = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
    if (editorService == null) return value;

    var listBox = new ListBox();
    listBox.Click += (sender, e) => editorService.CloseDropDown();
    foreach (var propertiy in typeof(MyLabelColors).GetProperties())
    {
    listBox.Items.Add(propertiy.Name);
    }
    editorService.DropDownControl(listBox);

    return (listBox.SelectedItem != null ? typeof(MyLabelColors).GetProperty(listBox.SelectedItem.ToString()).GetValue(null) : value);
    }
    }

    public class MyLabelColors
    {
    public static Color MyBlack { get => Color.FromArgb(1, 1, 1); }
    public static Color MyWhite { get => Color.FromArgb(254, 254, 254); }
    }
マルチポストを報告
違反を報告
引用返信 削除キー/
■34534 / ResNo.1)  Re[1]: デザイナのプロパティウィンドウで静的プロパティを選択したい
□投稿者/ Hongliang 大御所(586回)-(2020/09/16(Wed) 09:43:37)
  • アイコン試してはいないですが、以下のページが参考にならないでしょうか。
    http://www.comrade.co.jp/component/dotnetroom/kt_vsdn/kt_vs5b.htm
違反を報告
引用返信 削除キー/
■34536 / ResNo.2)  Re[2]: デザイナのプロパティウィンドウで静的プロパティを選択したい
□投稿者/ masa 一般人(2回)-(2020/09/17(Thu) 22:51:54)
  • アイコンNo34534に返信(Hongliangさんの記事)
    > 試してはいないですが、以下のページが参考にならないでしょうか。
    > http://www.comrade.co.jp/component/dotnetroom/kt_vsdn/kt_vs5b.htm
    回答頂きありがとうございます。

    ページに記載されていたInstanceDescriptorについて調べてみたところ、SystemColorsもColorConverter内でInstanceDescriptorによって実現されていることが分かりました。
    しかしColorConverterを継承してもColor構造体からMyLabelColorsの特定ができなかったため、
    自作のクラスを作成して以下のソースのようにすることで目的は達成できました。ありがとうございます。

    ただ、基本的には問題ないのですが、プロパティウィンドウで値を変更すると稀にDesigner.csのソースが「this.myLabel1.ForeColor = ((PropertyTest.MyLabelColor)(PropertyTest.MyLabelColor.MyWhite));」のようにキャストがついてしまうことがあります。
    VisualStudioを立ち上げた直後にプロパティウィンドウで値を変更すると「this.myLabel1.ForeColor = PropertyTest.MyLabelColor.MyWhite;」のようにキャストはつかず期待通りになります。
    常にキャストがつかないようにしたいのですが、引き続きお知恵を拝借できますでしょうか。よろしくお願い致します。

    public class MyLabel : Label
    {
    public new MyLabelColor ForeColor
    {
    get => _ForeColor;
    set
    {
    _ForeColor = value;
    base.ForeColor = _ForeColor.Color;
    }
    }
    private MyLabelColor _ForeColor;
    }

    public class MyLabelTypeConverter : TypeConverter
    {
    public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
    {
    return true;
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
    return new StandardValuesCollection(typeof(MyLabelColor).GetProperties().Select(p => p.Name).ToList());
    }

    public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
    {
    if (sourceType == typeof(string))
    {
    return true;
    }
    return base.CanConvertFrom(context, sourceType);
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
    if (value is string)
    {
    var myLabelColor = typeof(MyLabelColor).GetProperty(value.ToString())?.GetValue(null);
    if (myLabelColor != null)
    {
    return myLabelColor;
    }
    else
    {
    return new MyLabelColor("UnknownColor", Color.Transparent);
    }
    }
    return base.ConvertFrom(context, culture, value);
    }

    public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
    {
    if (destinationType == typeof(InstanceDescriptor))
    {
    return true;
    }
    return base.CanConvertTo(context, destinationType);
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
    {
    if (destinationType == typeof(InstanceDescriptor))
    {
    return new InstanceDescriptor(typeof(MyLabelColor).GetProperty(value.ToString()), null);
    }
    return base.ConvertTo(context, culture, value, destinationType);
    }
    }

    [TypeConverter(typeof(MyLabelTypeConverter))]
    public class MyLabelColor
    {
    public static MyLabelColor MyBlack => new MyLabelColor(nameof(MyBlack), Color.FromArgb(1, 1, 1));
    public static MyLabelColor MyWhite => new MyLabelColor(nameof(MyWhite), Color.FromArgb(254, 254, 254));

    public string Name;
    public Color Color;

    public MyLabelColor(string name, Color color)
    {
    this.Name = name;
    this.Color = color;
    }

    public override string ToString()
    {
    return this.Name;
    }
    }
違反を報告
引用返信 削除キー/
■34537 / ResNo.3)  Re[3]: デザイナのプロパティウィンドウで静的プロパティを選択したい
□投稿者/ masa 一般人(3回)-(2020/09/19(Sat) 23:41:10)
  • アイコンNo34536に返信
    上記サンプルでは何故かキャストがつくことがありましたが、実際に使用するソリューションでは特に問題ありませんでしたので、解決済みとさせていただきます。
    ありがとうございました。
解決み!
違反を報告
引用返信 削除キー/



スレッド内ページ移動 / << 0 >>

このスレッドに書きこむ

Mode/  Pass/


- Child Tree -