.net 带有嵌套控件的设计模式
在开发控件时,是否有人找到了设计模式问题的有用解决方案 问题是,如果嵌套控件,则DesignMode仅适用于第一级。第二级和更低级别的设计模式将始终返回FALSE 标准的破解方法是查看正在运行的进程的名称,如果它是“DevEnv.EXE”,那么它必须是studio,因此DesignMode是真的 问题是在注册表和其他奇怪的部分中查找ProcessName,最终结果是用户可能没有查看进程名所需的权限。此外,这条奇怪的路线非常慢。因此,我们不得不添加额外的hack来使用singleton,如果在请求进程名时抛出错误,则假定DesignMode为FALSE.net 带有嵌套控件的设计模式,.net,user-controls,.net,User Controls,在开发控件时,是否有人找到了设计模式问题的有用解决方案 问题是,如果嵌套控件,则DesignMode仅适用于第一级。第二级和更低级别的设计模式将始终返回FALSE 标准的破解方法是查看正在运行的进程的名称,如果它是“DevEnv.EXE”,那么它必须是studio,因此DesignMode是真的 问题是在注册表和其他奇怪的部分中查找ProcessName,最终结果是用户可能没有查看进程名所需的权限。此外,这条奇怪的路线非常慢。因此,我们不得不添加额外的hack来使用singleton,如果在请求
确定设计模式的一种很好的方法是有序的。如果能让微软在框架内部修复它,那就更好了 我自己从来没有遇到过这种情况,但你能不能从控件返回父链,看看设计模式是否设置在你的上方?设计模式是私有财产(据我所知)。答案是提供公开DesignMode道具的公共属性。然后可以cascasde备份用户控件链,直到遇到非用户控件或处于设计模式的控件。像这样的
public bool RealDesignMode()
{
if (Parent is MyBaseUserControl)
{
return (DesignMode ? true : (MyBaseUserControl) Parent.RealDesignMode;
}
return DesignMode;
}
所有用户控件都继承自MyBaseUserControl。或者,您可以实现一个公开“realdesgnmode”的接口
请注意,此代码不是实时代码,只是即兴思考。:) 我没有意识到你不能调用Parent.DesignMode(我也学到了一些关于C#中的“protected”的知识…) 这里是一个反射版本:(我怀疑将designModeProperty设置为静态字段可能有性能优势)
为什么不检查LicenseManager.UsageMode。 此属性的值可以是LicenseUsageMode.Runtime或LicenseUsageMode.Designtime 如果希望代码仅在运行时运行,请使用以下代码:
if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
{
bla bla bla...
}
回顾这个问题,我现在“发现”了5种不同的方法,如下所示:
System.ComponentModel.DesignMode property
System.ComponentModel.LicenseManager.UsageMode property
private string ServiceString()
{
if (GetService(typeof(System.ComponentModel.Design.IDesignerHost)) != null)
return "Present";
else
return "Not present";
}
public bool IsDesignerHosted
{
get
{
Control ctrl = this;
while(ctrl != null)
{
if((ctrl.Site != null) && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return false;
}
}
public static bool IsInDesignMode()
{
return System.Reflection.Assembly.GetExecutingAssembly()
.Location.Contains("VisualStudio"))
}
为了尝试并掌握提出的三个解决方案,我创建了一个小测试解决方案,其中包括三个项目:
- TestApp(winforms应用程序)
- 子控制(dll)
- 子子控件(dll)
//
///DesignMode属性无法正确地告诉您
///您处于设计模式。IsDesignerHosted是一个已更正的
///该属性的版本。
///(见https://connect.microsoft.com/VisualStudio/feedback/details/553305
///及http://stackoverflow.com/a/2693338/238419 )
///
公共住宅设计酒店
{
得到
{
if(LicenseManager.UsageMode==LicenseUsageMode.Designtime)
返回true;
Control ctrl=this;
while(ctrl!=null)
{
if((ctrl.Site!=null)和&ctrl.Site.DesignMode)
返回true;
ctrl=ctrl.Parent;
}
返回false;
}
}
我已经提交给微软;我怀疑它是否会出现在任何地方,但无论如何都要投票支持它,因为这显然是一个bug(无论它是否“按设计”)。我使用LicenseManager方法,但缓存构造函数中的值,以便在实例的整个生命周期中使用
public MyUserControl()
{
InitializeComponent();
m_IsInDesignMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
}
private bool m_IsInDesignMode = true;
public bool IsInDesignMode { get { return m_IsInDesignMode; } }
VB版本:
Sub New()
InitializeComponent()
m_IsInDesignMode = (LicenseManager.UsageMode = LicenseUsageMode.Designtime)
End Sub
Private ReadOnly m_IsInDesignMode As Boolean = True
Public ReadOnly Property IsInDesignMode As Boolean
Get
Return m_IsInDesignMode
End Get
End Property
这是我在表单中使用的方法:
/// <summary>
/// Gets a value indicating whether this instance is in design mode.
/// </summary>
/// <value>
/// <c>true</c> if this instance is in design mode; otherwise, <c>false</c>.
/// </value>
protected bool IsDesignMode
{
get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; }
}
//
///获取一个值,该值指示此实例是否处于设计模式。
///
///
///如果此实例处于设计模式,则为true;否则,错误。
///
保护布尔设计模式
{
获取{return DesignMode | | LicenseManager.UsageMode==LicenseUsageMode.Designtime;}
}
这样,即使DesignMode或LicenseManager属性失败,结果也将是正确的。因为这些方法都不可靠(DesignMode、LicenseManager)或有效(进程、递归检查),所以我使用的是
公共静态bool运行时{get;private set}
并在Main()方法中显式设置它 我们成功地使用了此代码:
public static bool IsRealDesignerMode(this Control c)
{
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
return true;
else
{
Control ctrl = c;
while (ctrl != null)
{
if (ctrl.Site != null && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv";
}
}
我的建议是对@blueraja danny pflughoeft进行优化。 此解决方案不是每次都计算结果,而是仅在第一次计算结果(对象无法将UsageMode从设计更改为运行时)
private bool?m_IsDesignerHosted=null//包含有关设计模式状态的信息
///
///DesignMode属性无法正确地告诉您
///您处于设计模式。IsDesignerHosted是一个已更正的
///该属性的版本。
///(见https://connect.microsoft.com/VisualStudio/feedback/details/553305
///及https://stackoverflow.com/a/2693338/238419 )
///
[可浏览(错误)]
公共住宅设计酒店
{
得到
{
if(m_IsDesignerHosted.HasValue)
返回m_IsDesignerHosted.Value;
其他的
{
if(LicenseManager.UsageMode==LicenseUsageMode.Designtime)
{
m_IsDesignerHosted=真;
返回
/// <summary>
/// Gets a value indicating whether this instance is in design mode.
/// </summary>
/// <value>
/// <c>true</c> if this instance is in design mode; otherwise, <c>false</c>.
/// </value>
protected bool IsDesignMode
{
get { return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; }
}
public static bool IsRealDesignerMode(this Control c)
{
if (System.ComponentModel.LicenseManager.UsageMode == System.ComponentModel.LicenseUsageMode.Designtime)
return true;
else
{
Control ctrl = c;
while (ctrl != null)
{
if (ctrl.Site != null && ctrl.Site.DesignMode)
return true;
ctrl = ctrl.Parent;
}
return System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv";
}
}
private bool? m_IsDesignerHosted = null; //contains information about design mode state
/// <summary>
/// The DesignMode property does not correctly tell you if
/// you are in design mode. IsDesignerHosted is a corrected
/// version of that property.
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and https://stackoverflow.com/a/2693338/238419 )
/// </summary>
[Browsable(false)]
public bool IsDesignerHosted
{
get
{
if (m_IsDesignerHosted.HasValue)
return m_IsDesignerHosted.Value;
else
{
if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
{
m_IsDesignerHosted = true;
return true;
}
Control ctrl = this;
while (ctrl != null)
{
if ((ctrl.Site != null) && ctrl.Site.DesignMode)
{
m_IsDesignerHosted = true;
return true;
}
ctrl = ctrl.Parent;
}
m_IsDesignerHosted = false;
return false;
}
}
}
public static class DesignTimeHelper
{
private static bool? _isAssemblyVisualStudio;
private static bool? _isLicenseDesignTime;
private static bool? _isProcessDevEnv;
private static bool? _mIsDesignerHosted;
/// <summary>
/// Property <see cref="Form.DesignMode"/> does not correctly report if a nested <see cref="UserControl"/>
/// is in design mode. InDesignMode is a corrected that property which .
/// (see https://connect.microsoft.com/VisualStudio/feedback/details/553305
/// and https://stackoverflow.com/a/2693338/238419 )
/// </summary>
public static bool InDesignMode(
this Control userControl,
string source = null)
=> IsLicenseDesignTime
|| IsProcessDevEnv
|| IsExecutingAssemblyVisualStudio
|| IsDesignerHosted(userControl);
private static bool IsExecutingAssemblyVisualStudio
=> _isAssemblyVisualStudio
?? (_isAssemblyVisualStudio = Assembly
.GetExecutingAssembly()
.Location.Contains(value: "VisualStudio"))
.Value;
private static bool IsLicenseDesignTime
=> _isLicenseDesignTime
?? (_isLicenseDesignTime = LicenseManager.UsageMode == LicenseUsageMode.Designtime)
.Value;
private static bool IsDesignerHosted(
Control control)
{
if (_mIsDesignerHosted.HasValue)
return _mIsDesignerHosted.Value;
while (control != null)
{
if (control.Site?.DesignMode == true)
{
_mIsDesignerHosted = true;
return true;
}
control = control.Parent;
}
_mIsDesignerHosted = false;
return false;
}
private static bool IsProcessDevEnv
=> _isProcessDevEnv
?? (_isProcessDevEnv = Process.GetCurrentProcess()
.ProcessName == "devenv")
.Value;
}