【问题标题】:IWindowsFormsEditorService delay after closing关闭后 IWindowsFormsEditorService 延迟
【发布时间】:2019-03-15 14:25:46
【问题描述】:

我需要将自定义属性值编辑器集成到PropertyGrid 控件中。代码如下

internal class VariableTypeEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.DropDown;
    }

    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService service = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

        Type type = context.GetType();
        PropertyInfo property = type.GetProperty("OwnerGrid");

        IPlugIn plug = context.Instance as IPlugIn;

        if (service != null && property != null
                            && plug != null)
        {
            PropertyGrid owner = property.GetValue(context) as PropertyGrid;

            if (owner != null)
            {
                Collection<VariableWrapper> variables = owner.Tag as Collection<VariableWrapper>;

                if (variables != null)
                {
                    VariableEditorForm editor = new VariableEditorForm();
                    editor.Value = plug.VariableName;
                    editor.Variables = variables.Select(o => o.Variable).Where(o => o.ValueType == plug.VariableType).ToArray();
                    editor.TopLevel = false;
                    editor.FormClosed += new FormClosedEventHandler((sender, args) =>
                    {
                        service.CloseDropDown();
                    });

                    service.DropDownControl(editor);
                    value = editor.Value;
                }
            }
        }

        return value;
    }
}

我希望它以这种方式工作:

  • 要更改属性的值,用户打开下拉菜单VariableEditorForm(使用 PropertyGrid)
  • 用户选择VariableEditorForm 中列出的值之一,然后VariableEditorForm 将自动关闭

现在可以了。但由于某种原因,EditValue 方法需要 2-3 秒才能返回其值。

为什么service.DropDownControl(editor) 关闭后没有立即返回?

【问题讨论】:

  • 这是出乎意料的。您是否尝试过在另一个上调用 CloseDropDown (在 FormClosed 之前)?你试过调试吗?你确定没有异常发生吗(属性网格可以默默吞下很多错误)。
  • @SimonMourier - 我做了几个实验,发现 IWindowsFormsEditorService 等待 MainThread 空闲(例如从渲染主窗口)。
  • 如果没有完整的复制代码,很难进一步挖掘。
  • 我看到的唯一一件事是您没有处理表单,但我怀疑这是问题所在。
  • @TnTinMn 请看看我的回答。您对如何改进它有任何想法吗?谢谢。

标签: c# winforms propertygrid uitypeeditor


【解决方案1】:

我设法找到了解决方案。我不喜欢,但它有效。代码如下。

            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
            {
                IWindowsFormsEditorService service = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;

                Type type = context.GetType();
                PropertyInfo property = type.GetProperty("OwnerGrid");

                IPlugIn plug = context.Instance as IPlugIn;

                if (service != null && property != null
                                    && plug != null)
                {
                    PropertyGrid owner = property.GetValue(context) as PropertyGrid;

                    if (owner != null)
                    {
                        Collection<VariableWrapper> variables = owner.Tag as Collection<VariableWrapper>;

                        if (variables != null)
                        {
                            VariableEditorForm editor = new VariableEditorForm();
                            editor.Value = plug.VariableName;
                            editor.Variables = variables.Select(o => o.Variable).Where(o => o.ValueType == plug.VariableType).ToArray();
                            editor.TopLevel = false;
                            editor.FormClosed += new FormClosedEventHandler((sender, args) =>
                            {
                                // disable main form rendering
                                User32.PostMessage(Process.GetCurrentProcess().MainWindowHandle, Messages.WM_DISABLE_RENDER, IntPtr.Zero, IntPtr.Zero);
                                service.CloseDropDown();
                            });

                            service.DropDownControl(editor);

                            // enable main form rendering
                            User32.PostMessage(Process.GetCurrentProcess().MainWindowHandle, Messages.WM_ENABLE_RENDER, IntPtr.Zero, IntPtr.Zero);
                            value = editor.Value;
                            editor.Dispose();
                        }
                    }
                }

                return value;
            }

事情是我的主窗体上有一个面板,它使用计时器来不断地呈现自己。我注意到每次禁用该计时器时我的问题都会消失。所以没有更好的解决方案,我决定将消息发布到我的主窗体以启用/禁用提到的计时器。

如果有人能为我的问题提供适当的解决方案,我将不胜感激。

【讨论】:

    【解决方案2】:

    是否可以有 const 的值:WM_DISABLE_RENDERWM_ENABLE_RENDER

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 2021-06-14
    • 2017-01-29
    • 1970-01-01
    相关资源
    最近更新 更多