延续这个问题,是否可能从对象构造函数内部检测当前处于设计模式还是运行时模式?
我知道这可能不可能实现,并且我将不得不改变我的需求,但现在我对这个具体的问题感兴趣。
System.ComponentModel
命名空间中使用 LicenseUsageMode 枚举:bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
你是在寻找这样的内容吗:
public static bool IsInDesignMode()
{
if (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1)
{
return true;
}
return false;
}
您也可以通过检查进程名称来执行此操作:
if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
return true;
据我所知,组件 Component 没有 DesignMode 属性。这个属性是由 Control 提供的。但问题是,当 CustomControl 位于设计器中的一个窗体中时,这个 CustomControl 就运行在运行时模式下。
我经验过,DesignMode 属性只在窗体中才能正常工作。
控件(表单、用户控件等)继承了Component类
,该类具有bool类型的DesignMode属性
,因此:
if(DesignMode)
{
//If in design mode
}
OnHandleCreated
。 - Ray重要提示:
使用Windows Forms或WPF有所不同!
它们具有不同的设计师和需要不同的检查。此外,在混合使用Forms和WPF控件时会很棘手。(例如,在Forms窗口中使用WPF控件)
如果您只使用Windows Forms,请使用以下方法:
Boolean isInWpfDesignerMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
如果您只使用WPF,请使用以下检查:
Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");
mixed usage 的意思是混合使用。
Boolean isInWpfDesignerMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");
if (isInWpfDesignerMode || isInFormsDesignerMode)
{
// is in any designer mode
}
else
{
// not in designer mode
}
为了调试,可以使用MessageBox来查看当前模式:
// show current mode
MessageBox.Show(String.Format("DESIGNER CHECK: WPF = {0} Forms = {1}", isInWpfDesignerMode, isInFormsDesignerMode));
注意:
您需要添加命名空间 System.ComponentModel 和 System.Diagnostics。
if (!DesignMode)
,以确保它不会在设计时崩溃。 - BitterblueLicenseManager.UsageMode
只在构造函数中可靠地工作,而 DesignMode
只在构造函数之外工作,并且并非总是有效。这是我的经验,也是 在 GitHub 上的讨论中所说的。这可以在我为此测试创建的 UserControls 中显示出来。每个 UC 都有 3 个标签:
它的 (项目名称)
和 类型名称
以下值:
DesignMode
(true
: "DM=1"
),LicenseManager.UsageMode == LicenseUsageMode.Designtime
(true
: "local_LM-DT=1"),LicenseManager.UsageMode == LicenseUsageMode.Designtime
(true
: "ctor_LM-DT=1")以上所有值都在构造函数 ("CTOR") 内获取,并在从构造函数调用的方法 ("CFCtor") 内获取
与第2点相同的值
以上所有值都在 Load
事件 ("Load()") 内获取,并在从 Load
事件调用的方法 ("CFLoad") 内获取
我创建的用户控件和窗体如下(所有截图都显示在 WinForms 设计器中):
UserControl1
:
UserControl1a
:
UserControl1
UserControl2
: 包含
UserControl1
UserControl1a
UserControl3
:
UserControl2
设计器执行嵌入式UserControls的构造函数和事件。
2级嵌套:第二个嵌套级别中UserControl中的值是错误的。
Form1
:
UserControl1
UserControl1a
UserControl2
UserControl3
.
设计器执行嵌入式UserControls的构造函数和事件。
3级嵌套:第二个和第三个嵌套级别中UserControl中的值是错误的。
private LicenseUsageMode m_ctorLMUsageMode = LicenseManager.UsageMode;
为了完整起见,这是一些可以用来复现测试的代码:
public static string CreateText(bool i_isInDesignMode, LicenseUsageMode i_localLicenseUsageMode, LicenseUsageMode i_ctorLicenseUsageMode)
{
return $"DM={(i_isInDesignMode ? 1 : 0)} local_LM-DT={(i_localLicenseUsageMode == LicenseUsageMode.Designtime ? 1 : 0)} ctor_LM-DT={(i_ctorLicenseUsageMode == LicenseUsageMode.Designtime ? 1 : 0)}";
}
其他用户控件相同或类似:
public partial class UserControl1 : UserControl
{
private LicenseUsageMode m_ctorLMUsageMode = LicenseManager.UsageMode;
public UserControl1()
{
InitializeComponent();
label2.Text = $"CTOR: {CInitTester.CreateText (DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
CalledFromCtor();
}
private void UserControl1_Load(object sender, EventArgs e)
{
label3.Text = $"Load(): {CInitTester.CreateText(DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
CalledFromLoad();
}
private void CalledFromCtor()
{
label2.Text += $"\r\nCFCtor: {CInitTester.CreateText (DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
}
private void CalledFromLoad()
{
label3.Text += $"\r\nCFLoad: {CInitTester.CreateText (DesignMode, LicenseManager.UsageMode, m_ctorLMUsageMode)}";
}
}
if (DesignerProperties.GetIsInDesignMode(this))
{
...
}
当我在Visual Studio 2019上创建.NET Core 3.1的WinForms应用程序时,我无法使这些解决方案中的任何一个适用于我。
对我而言,Appllication.ProcessName
和Process.ProcessName
都返回"DesignToolsServer"
,而LicenseManager.UsageMode
在控件位于另一个控件或仅位于表单本身时返回LicenseUsageMode.Runtime
。
我使用Application.ProcessName == "DesignToolsServer"
使其正常工作。
与设计师的合作配合下,它可以用于控件、组件中,以及所有位置。
private bool getDesignMode()
{
IDesignerHost host;
if (Site != null)
{
host = Site.GetService(typeof(IDesignerHost)) as IDesignerHost;
if (host != null)
{
if (host.RootComponent.Site.DesignMode) MessageBox.Show("Design Mode");
else MessageBox.Show("Runtime Mode");
return host.RootComponent.Site.DesignMode;
}
}
MessageBox.Show("Runtime Mode");
return false;
}
MessageBox.Show(
这些代码行应该被移除,因为它们只是让我确认代码是否正确工作。
LicenseManager.UsageMode
,并且该UC A被另一个程序集中的另一个用户控件或窗体B所使用,则此方法将无法正常工作。在这种情况下,我仍然会得到Runtime
而不是DesignTime
。 - Tobias Knauss