none
MultilineStringEditor使用時に表示されるエディットボックスの幅について RRS feed

  • 質問

  • System.Windows.Forms.PropertyGridを使用してWindowsフォームアプリケーションを作成しています。

    MultilineStringEditorを使用して、複数行の入力が可能なエディタをPropertyGridに表示しているのですが、初回表示時にエディタの幅が狭くなってしまう問題が発生しています。

    .NET Framework 3.5でビルドすると発生し、.NET Framework 4でビルドすると発生しないことは分かっているのですが、この問題は.NET Framework 3.5のバグでしょうか??

    • 開発環境は「Visual Studio 2010 C#」、「.NET Framework 3.5」です。
    • PropertyGridからフォーカスを外して別のコントロール選択後、再びPropertyGridに戻ると、現象が再現します。初回のみエディタの幅が狭くなります。
    2016年8月15日 6:26

回答

  • 回答ではないのですが、この先、どういったコメントを期待されていますか?

    .NET 3.5 と .NET 4 で振る舞いが違うことからは、「不具合と認定して修正した」や「割り切りで仕様としていたが、変更した」といった可能性が予想されます。
    それをはっきりさせるには、Microsoft の有償サポートで聞き出す以外の手立てはほぼありません。

    サポート情報(KB)に同一の症状を述べたものがあるとか、Connect にバグレポートがあってそれに対して Microsoft が認める発言をしているなら、はっきりしますが、それを探し出すことは難しいと思われます。
    (プロフェッショナルサポートなど、有償サポートの中でも下位に位置づけられるサポートでは、公開されている情報がないなどの理由によって、答えを得られないこともあります)

    以上のことから、「バグでしょうか?」とこのフォーラムで問われても、その先が続かないのではないかと考えたために、冒頭の疑問を提示させていただきました。
    回避策がないか?という情報募集であれば、その旨、お書き添えいただければと思います。

    • 回答としてマーク YKuma333 2016年8月16日 0:26
    2016年8月15日 8:05
    モデレータ
  • むりやり変更してみる

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Forms;
    using System.ComponentModel.Design;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                TextBox text = new TextBox();
                this.Controls.Add(text);
    
                PropertyGrid pg = new PropertyGrid();
                pg.Top = text.Height;
                pg.Height = this.ClientSize.Height - pg.Top;
                pg.Width = this.ClientSize.Width;
                pg.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
                pg.SelectedObject = new TestItem();
                this.Controls.Add(pg);
    
                PropertyGridTool.FixNet35MultilineStringEditorWidth(pg);
            }
    
            class TestItem
            {
                [EditorAttribute(typeof(MultilineStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
                public string Text { get; set; }
            }
        }
    
    
        class PropertyGridTool
        {
            public static void FixNet35MultilineStringEditorWidth(PropertyGrid pg)
            {
                if (System.Environment.Version.Major < 4)
                {
                    List<Button> buttons = new List<Button>();
                    FindControl<Button>(pg, buttons);
                    foreach (Button btn in buttons.Where((b) => b.GetType().FullName == "System.Windows.Forms.PropertyGridInternal.DropDownButton"))
                    {
                        //DropDownボタンのClickイベントに割り込ませる
                        var ei = btn.GetType().GetEvent("Click");
                        var fi = typeof(Control).GetField("EventClick", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
                        var pi = typeof(Component).GetProperty("Events", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                        var eventList = (System.ComponentModel.EventHandlerList)pi.GetValue(btn, null);
                        var evkey = fi.GetValue(null);
                        var ev = eventList[evkey];
                        var invocationList = ev.GetInvocationList().ToArray();
                        foreach (EventHandler eh in invocationList)
                        {
                            ei.RemoveEventHandler(btn, eh);
                        }
                        btn.Tag = invocationList;
                        btn.Click += new EventHandler(btn_Click);
                    }
                }
            }
    
            private static void btn_Click(object sender, EventArgs e)
            {
                Button btn = (Button)sender;
                Control parent = btn.Parent;
                PropertyGrid pg = null;
                while (pg == null)
                {
                    pg = parent as PropertyGrid;
                    parent = parent.Parent;
                }
                if (pg != null && pg.SelectedGridItem != null && btn.Tag is Delegate[])
                {
                    var editor = pg.SelectedGridItem.PropertyDescriptor.GetEditor(typeof(System.Drawing.Design.UITypeEditor)) as System.ComponentModel.Design.MultilineStringEditor;
                    if (editor != null)
                    {
                        var opens = Application.OpenForms.Cast<Form>().ToArray();
                        pg.BeginInvoke((Action)(() =>
                            {
                                var newOpens = Application.OpenForms.Cast<Form>().ToArray();
                                var newForm = newOpens.Except(opens).FirstOrDefault();
                                if (newForm != null)
                                {
                                    if (newForm.Controls.Count == 1)
                                    {
                                        var child = newForm.Controls[0];
                                        if (newForm.ClientSize.Width < child.MinimumSize.Width || newForm.ClientSize.Height < child.MinimumSize.Height)
                                        {
                                            child.Focus();
    
                                            int diffX = newForm.Width - child.MinimumSize.Width;
                                            newForm.ClientSize = child.MinimumSize;
                                            newForm.Left += diffX;
                                            newForm.Left = Math.Max(newForm.Left, Screen.GetWorkingArea(newForm).Left);
                                        }
                                    }
                                }
                            }));
    
                        Delegate[] dels = (Delegate[])btn.Tag;
                        btn.Tag = null;
                        btn.Click -= btn_Click;
                        foreach (EventHandler eh in dels)
                        {
                            btn.Click += eh;
                        }
                        foreach (EventHandler eh in dels)
                        {
                            eh.Invoke(sender, e);
                        }
                    }
                }
            }
    
            public static void FindControl<T>(Control parent, List<T> list) where T : Control
            {
                foreach (Control child in parent.Controls)
                {
                    if (child is T)
                    {
                        list.Add((T)child);
                    }
                    FindControl<T>(child, list);
                }
    
            }
        }
    }
    #バグだとしてもセキュリティ修正以外で3.5が修正されることはもう無いと思いますが

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク YKuma333 2016年8月16日 0:26
    2016年8月15日 13:11

すべての返信

  • 回答ではないのですが、この先、どういったコメントを期待されていますか?

    .NET 3.5 と .NET 4 で振る舞いが違うことからは、「不具合と認定して修正した」や「割り切りで仕様としていたが、変更した」といった可能性が予想されます。
    それをはっきりさせるには、Microsoft の有償サポートで聞き出す以外の手立てはほぼありません。

    サポート情報(KB)に同一の症状を述べたものがあるとか、Connect にバグレポートがあってそれに対して Microsoft が認める発言をしているなら、はっきりしますが、それを探し出すことは難しいと思われます。
    (プロフェッショナルサポートなど、有償サポートの中でも下位に位置づけられるサポートでは、公開されている情報がないなどの理由によって、答えを得られないこともあります)

    以上のことから、「バグでしょうか?」とこのフォーラムで問われても、その先が続かないのではないかと考えたために、冒頭の疑問を提示させていただきました。
    回避策がないか?という情報募集であれば、その旨、お書き添えいただければと思います。

    • 回答としてマーク YKuma333 2016年8月16日 0:26
    2016年8月15日 8:05
    モデレータ
  • むりやり変更してみる

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Windows.Forms;
    using System.ComponentModel.Design;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                TextBox text = new TextBox();
                this.Controls.Add(text);
    
                PropertyGrid pg = new PropertyGrid();
                pg.Top = text.Height;
                pg.Height = this.ClientSize.Height - pg.Top;
                pg.Width = this.ClientSize.Width;
                pg.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
                pg.SelectedObject = new TestItem();
                this.Controls.Add(pg);
    
                PropertyGridTool.FixNet35MultilineStringEditorWidth(pg);
            }
    
            class TestItem
            {
                [EditorAttribute(typeof(MultilineStringEditor), typeof(System.Drawing.Design.UITypeEditor))]
                public string Text { get; set; }
            }
        }
    
    
        class PropertyGridTool
        {
            public static void FixNet35MultilineStringEditorWidth(PropertyGrid pg)
            {
                if (System.Environment.Version.Major < 4)
                {
                    List<Button> buttons = new List<Button>();
                    FindControl<Button>(pg, buttons);
                    foreach (Button btn in buttons.Where((b) => b.GetType().FullName == "System.Windows.Forms.PropertyGridInternal.DropDownButton"))
                    {
                        //DropDownボタンのClickイベントに割り込ませる
                        var ei = btn.GetType().GetEvent("Click");
                        var fi = typeof(Control).GetField("EventClick", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
                        var pi = typeof(Component).GetProperty("Events", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                        var eventList = (System.ComponentModel.EventHandlerList)pi.GetValue(btn, null);
                        var evkey = fi.GetValue(null);
                        var ev = eventList[evkey];
                        var invocationList = ev.GetInvocationList().ToArray();
                        foreach (EventHandler eh in invocationList)
                        {
                            ei.RemoveEventHandler(btn, eh);
                        }
                        btn.Tag = invocationList;
                        btn.Click += new EventHandler(btn_Click);
                    }
                }
            }
    
            private static void btn_Click(object sender, EventArgs e)
            {
                Button btn = (Button)sender;
                Control parent = btn.Parent;
                PropertyGrid pg = null;
                while (pg == null)
                {
                    pg = parent as PropertyGrid;
                    parent = parent.Parent;
                }
                if (pg != null && pg.SelectedGridItem != null && btn.Tag is Delegate[])
                {
                    var editor = pg.SelectedGridItem.PropertyDescriptor.GetEditor(typeof(System.Drawing.Design.UITypeEditor)) as System.ComponentModel.Design.MultilineStringEditor;
                    if (editor != null)
                    {
                        var opens = Application.OpenForms.Cast<Form>().ToArray();
                        pg.BeginInvoke((Action)(() =>
                            {
                                var newOpens = Application.OpenForms.Cast<Form>().ToArray();
                                var newForm = newOpens.Except(opens).FirstOrDefault();
                                if (newForm != null)
                                {
                                    if (newForm.Controls.Count == 1)
                                    {
                                        var child = newForm.Controls[0];
                                        if (newForm.ClientSize.Width < child.MinimumSize.Width || newForm.ClientSize.Height < child.MinimumSize.Height)
                                        {
                                            child.Focus();
    
                                            int diffX = newForm.Width - child.MinimumSize.Width;
                                            newForm.ClientSize = child.MinimumSize;
                                            newForm.Left += diffX;
                                            newForm.Left = Math.Max(newForm.Left, Screen.GetWorkingArea(newForm).Left);
                                        }
                                    }
                                }
                            }));
    
                        Delegate[] dels = (Delegate[])btn.Tag;
                        btn.Tag = null;
                        btn.Click -= btn_Click;
                        foreach (EventHandler eh in dels)
                        {
                            btn.Click += eh;
                        }
                        foreach (EventHandler eh in dels)
                        {
                            eh.Invoke(sender, e);
                        }
                    }
                }
            }
    
            public static void FindControl<T>(Control parent, List<T> list) where T : Control
            {
                foreach (Control child in parent.Controls)
                {
                    if (child is T)
                    {
                        list.Add((T)child);
                    }
                    FindControl<T>(child, list);
                }
    
            }
        }
    }
    #バグだとしてもセキュリティ修正以外で3.5が修正されることはもう無いと思いますが

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク YKuma333 2016年8月16日 0:26
    2016年8月15日 13:11
  • Azulean様、
    お返事ありがとうございます。ここで質問すべき内容かどうか悩んだのですが、何かご存知の方がいればと思い質問させて頂いた次第です。
    ご指摘頂いたとおり、"バグかどうか"ということについては、有償サポートで回答を得るべき問いでした。
    アドバイスありがとうございました。

    2016年8月16日 0:23
  • gekka様、
    回避策についてのご提案ありがとうございます。まさか本問題を実装で回避することができるとは・・・!!考えつきませんでした。

    早速、修正して動かしてみたところ、.NET 3.5でもエディタの幅を広げて表示することができました。大変勉強になりました。
    ありがとうございました。とても助かりました。
    2016年8月16日 0:26