Lately, I received a bug report for Ninject.Web that it is not working properly together with ASP.NET dynamic data. The problem is that on postback (e.g. when Inserting, Deleting, Editing a record) the table is not shown anymore.
Some debuging showed that the problem is caused by a IHttpModule that recursively iterates through all controls of a page after it is initialized. As soon as this module accesses the Controls property get accessor of FormView or GridView the problem occurs. If this type of controls is skiped everything is fine. The following code shows the module:
public class NinjectHttpModule : DisposableObject, IHttpModule
{
private HttpApplication httpApplication;
public void Init(HttpApplication context)
{
this.httpApplication = context;
this.httpApplication.PreRequestHandlerExecute += this.OnPreRequestHandlerExecute;
}
private static void InjectUserControls(Control parent)
{
if (parent == null)
{
return;
}
foreach (Control control in parent.Controls)
{
if (control is UserControl)
{
// KernelContainer.Inject(control); This is irrelevant for the question.
}
InjectUserControls(control);
}
}
private void OnPreRequestHandlerExecute(object sender, EventArgs e)
{
var page = this.httpApplication.Context.CurrentHandler as Page;
if (page == null)
{
return;
}
KernelContainer.Inject(page);
page.InitComplete += (src, args) => InjectUserControls(page);
}
}
If this code is changed so that the iteration through the child controls of DataBoundControls is delayed to the DataBound event everything is fine. Shown by the next code snippet:
private static void InjectUserControls(Control parent, bool skipDataBoundControls)
{
if (parent == null)
{
return;
}
if (skipDataBoundControls)
{
var dataBoundControl = parent as DataBoundControl;
if (dataBoundControl != null)
{
dataBoundControl.DataBound += InjectDataBoundControl;
return;
}
}
foreach (Control control in parent.Controls)
{
if (control is UserControl)
{
KernelContainer.Inject(control);
}
InjectUserControls(control, skipDataBoundControls);
}
}
private static void InjectDataBoundControl(object sender, EventArgs e)
{
var dataBoundControl = sender as DataBoundControl;
if (dataBoundControl != null)
{
dataBoundControl.DataBound -= InjectDataBoundControl;
InjectUserControls(dataBoundControl, false);
}
}
Because I'm completely unfamiliar with System.Web.DynamicData I'd like to know some things to get a better feeling about how to fix this bug:
Why does this problem occur? I mean it's only a simple read access to the Controls property.
What side effects can the change above have?
Is it still early enough to inject the controls after the data bound event?
Do you think this is a valid bug fix for this problem?
Certainly puzzling behavior, as can sometimes happen in WebForms with the many phases of execution.
Even though it's just a simple read access to the Controls property, this property can actually do a lot of work to return the child controls. In particular, it can't return the child controls unless they have been created, and that creation normally does not occur until later in the page life cycle. So by accessing it in InitComplete, the children end up getting created prematurely, before some important Dynamic Data hookups have happened, causing some controls to be missing. Yes, I realize that the end result behavior seems to make little sense, which is why some people favor the straightforwardness of MVC :)
As an alternate possible workaround, could you try moving your injection from InitComplete to PreLoad? e.g.
page.PreLoad += (src, args) => InjectUserControls(page);
I'm pretty sure that'll address the problem, though I'm less sure whether this will cause issues with your KernelContainer.Inject logic. Give it a try, since it's simpler than your workaround.
If that doesn't work, I think your workaround is ok, as it delays the enumeration until the children are created. As for 'Is it still early enough to inject the controls after the data bound event', I think that depends in exactly what KernelContainer.Inject does, and what expectations it has on the state of the control.
i make a function that uses a control as a parameter, and i use the control's property 'enable'.
the problem is that the control have Enable=false and inside the function it's true,
any ideas why?
protected override void OnPaint(PaintEventArgs pevent)
{
try
{
...
Shared.DrawTextByAlignment(pevent.Graphics, this, this.TextAlign);
}
catch (Exception ex) { MessageBox.Show("Button:OnPaint\n" + ex.Message);
}
static public void DrawTextByAlignment(Graphics g, Control myControl, ContentAlignment TextAlign)
{
...
Brush myBrush;
if (myControl.Enabled) myBrush = new SolidBrush(myControl.ForeColor);
else myBrush = Brushes.Gray;
...
}
When passing a control, you are almost universally talking about a class / object-instance, so all you are passing is the reference to the control - the control itself is identical.
One possible cause of this is an incorrect check:
if(ctrl.Enabled = true) { // spot the assignment!
DoSomething(ctrl);
}
which should be:
if(ctrl.Enabled == true) {
DoSomething(ctrl);
}
or just:
if(ctrl.Enabled) {
DoSomething(ctrl);
}
but the compiler would tell you that in a warning...
Assignment in conditional expression is always constant; did you mean to use == instead of = ?
This leaves only a few options:
the Enabled has genuinely changed, perhaps due to a state-change such as moving it in a control tree
the Enabled property defies all sanity and changes upon inspection
the Enabled property is thread-specific and you are talking to it from multiple threads
or, there is something else going on in your code that your question doesn't tell us, but the source might
I rather expect it to be the last option...
I think you might be need Visible property instead on enabled property.
Because Enable = false the control does not create any changes
If you derive a class from Control and override the Enabled property using the new keyword, your function will still access Control.Enabled. Change the signature to
static public void DrawTextByAlignment(..., MyControl myControl, ...)
Is there a variable or a preprocessor constant that allows to know that the code is executed within the context of Visual Studio?
Try Debugger.IsAttached or DesignMode property or get ProcessName or a combination, as appropriate
Debugger.IsAttached // or
LicenseUsageMode.Designtime // or
System.Diagnostics.Process.GetCurrentProcess().ProcessName
Here is a sample
public static class DesignTimeHelper {
public static bool IsInDesignMode {
get {
bool isInDesignMode = LicenseManager.UsageMode == LicenseUsageMode.Designtime || Debugger.IsAttached == true;
if (!isInDesignMode) {
using (var process = Process.GetCurrentProcess()) {
return process.ProcessName.ToLowerInvariant().Contains("devenv");
}
}
return isInDesignMode;
}
}
}
The DesignMode property isn't always accurate. We have had use this method so that it works consistently:
protected new bool DesignMode
{
get
{
if (base.DesignMode)
return true;
return LicenseManager.UsageMode == LicenseUsageMode.Designtime;
}
}
The context of your call is important. We've had DesignMode return false in the IDE if running in an event under certain circumstances.
There is the DesignMode property for Components. It is handy when you use the Design Viewer of VS.
But when you talk about debugging in Visual Studio you need to use the Debugger.IsAttached property. Then, you can use
#if DEBUG
#endif
too
I think the simplest and most reliable way to determine if your extension is executed in the WinForms designer is to check the current process.
public static bool InVisualStudio() {
return StringComparer.OrdinalIgnoreCase.Equals(
"devenv",
Process.CurrentProcess.ProcessName);
}
I use this extension method:
internal static class ControlExtension
{
public static bool IsInDesignMode(this Control control)
{
while (control != null)
{
if (control.Site != null && control.Site.DesignMode)
return true;
control = control.Parent;
}
return false;
}
}
There is a DesignMode property that you can check but in my experience it's not always accurate. You could also check to see if the executable is DevEnv.exe
Take a look here. Might make this question a dup but it all depends on what you're trying to accomplish.
You can use this:
protected static bool IsInDesigner
{
get { return (Assembly.GetEntryAssembly() == null); }
}
I use this code to distinguish whether it's running in Visual Studio or if it's deployed to customers.
if (ApplicationDeployment.IsNetworkDeployed) {
// do stuff
} else {
// do stuff (within Visual Studio)
}
Works fine for me for ages. I skip some logic when inside Visual Studio (such as logging in to application etc).
I want to add to this that in Visual Studio 2022 with .Net 6, the process that actually opens winforms designers is called DesignToolsServer. From my experience so far, DesignMode works outside of the constructor and checking for ProcessName = "DesignToolsServer" works within the constructor.
Following-on from this question, is it possible to detect whether one is in design or runtime mode from within an object's constructor?
I realise that this may not be possible, and that I'll have to change what I want, but for now I'm interested in this specific question.
You can use the LicenceUsageMode enumeration in the System.ComponentModel namespace:
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
Are you looking for something like this:
public static bool IsInDesignMode()
{
if (Application.ExecutablePath.IndexOf("devenv.exe", StringComparison.OrdinalIgnoreCase) > -1)
{
return true;
}
return false;
}
You can also do it by checking process name:
if (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv")
return true;
Component ... as far as I know does not have the DesignMode property. This property is provided by Control. But the problem is when CustomControl is located in a Form in the designer, this CustomControl is running in runtime mode.
I have experienced that the DesignMode property works correct only in Form.
Controls(Forms, UserControls etc.) inherit Component class which has bool property DesignMode so:
if(DesignMode)
{
//If in design mode
}
IMPORTANT
There is a difference of using Windows Forms or WPF!!
They have different designers and and need different checks.
Additionally it's tricky when you mix Forms and WPF controls. (e.g. WPF controls inside of a Forms window)
If you have Windows Forms only, use this:
Boolean isInWpfDesignerMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
If you have WPF only, use this check:
Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");
If you have mixed usage of Forms and WPF, use a check like this:
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
}
To see the current mode you can show a MessageBox for debugging:
// show current mode
MessageBox.Show(String.Format("DESIGNER CHECK: WPF = {0} Forms = {1}", isInWpfDesignerMode, isInFormsDesignerMode));
Remark:
You need to add the namespaces System.ComponentModel and System.Diagnostics.
You should use Component.DesignMode property. As far as I know, this shouldn't be used from a constructor.
You can use this
if (DesignerProperties.GetIsInDesignMode(this))
{
...
}
Like many others, I have had this problem several times already when designing Windows Forms UserControls.
But today, I had a situation where none of the mentioned solutions worked for me.
The problem is, that LicenseManager.UsageMode only works reliably in the constructor, while DesignMode only works outside the constructor and not always. This is my experience, and this is what is said in a discussion on GitHub.
And another problem comes with inheritance, and embedding user controls in another user controls in another user controls. At the latest in the 2nd level of embedding a user controls, both ways fail!
This can be shown in the UserControls that I created for this test. Every UC has 3 labels:
its (project name) and type name
The values of
DesignMode (true: "DM=1"),
LicenseManager.UsageMode == LicenseUsageMode.Designtime, queried locally, (true: "local_LM-DT=1")
LicenseManager.UsageMode == LicenseUsageMode.Designtime, queried from a private field that was written in the constructor (true: "ctor_LM-DT=1")
all taken inside the constructor ("CTOR") and inside a method that was called from the constructor ("CFCtor")
The same values as in 2)
all taken inside the Load event ("Load()") and inside a method that was called from the Load event ("CFLoad")
The UserControls and the Form that I created are (all screenshots shown them in the WinForms Designer):
UserControl1:
contains 3 labels
The Designer does not execute the construtor or events, therefore the labels are not filled.
UserControl1a:
inherits from UserControl1
contains 2 more labels
The Designer executes the construtor and events of the parent UserControl.
UserControl2: contains
contains 3 labels
contains 1 UserControl1
contains 1 UserControl1a
The Designer executes the construtors and events of the embedded UserControls.
Only 1 level of embedding.
UserControl3:
contains 3 labels
contains 1 UserControl2
The Designer executes the construtors and events of the embedded UserControls.
2 level of embedding: The values inside the UserControl at 2nd embedding level are wrong.
Form1:
contains 3 labels
contains 1 UserControl1
contains 1 UserControl1a
contains 1 UserControl2
contains 1 UserControl3.
The Designer executes the construtors and events of the embedded UserControls.
3 level of embedding: The values inside the UserControl at 2nd and 3rd embedding level are wrong.
As you can see from the screenshots, "ctor_LM-DT" is always 1.
This means, that storing the value from the LicenseManager in a member field is necessary to get a valid status of the Designer usage:
private LicenseUsageMode m_ctorLMUsageMode = LicenseManager.UsageMode;
For the sake of completeness, here's some of my code that can be used to reproduce the test:
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)}";
}
The other UserControls are identical or similar:
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)}";
}
}
Another interesting method is described on that blog: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or-usermode/
Basically, it tests for the executing assembly being statically referenced from the entry assembly. It circumvents the need to track assembly names ('devenv.exe', 'monodevelop.exe'..).
However, it does not work in all other scenarios, where the assembly is dynamically loaded (VSTO being one example).
With cooperation of the designer... It can be used in Controls, Components, in all places
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( lines should be removed. It only makes me sure it works correctly.
This is the method I used in my project:
//use a Property or Field for keeping the info to avoid runtime computation
public static bool NotInDesignMode { get; } = IsNotInDesignMode();
private static bool IsNotInDesignMode()
{
/*
File.WriteAllLines(#"D:\1.log", new[]
{
LicenseManager.UsageMode.ToString(), //not always reliable, e.g. WPF app in Blend this will return RunTime
Process.GetCurrentProcess().ProcessName, //filename without extension
Process.GetCurrentProcess().MainModule.FileName, //full path
Process.GetCurrentProcess().MainModule.ModuleName, //filename
Assembly.GetEntryAssembly()?.Location, //null for WinForms app in VS IDE
Assembly.GetEntryAssembly()?.ToString(), //null for WinForms app in VS IDE
Assembly.GetExecutingAssembly().Location, //always return your project's output assembly info
Assembly.GetExecutingAssembly().ToString(), //always return your project's output assembly info
});
//*/
//LicenseManager.UsageMode will return RunTime if LicenseManager.context is not present.
//So you can not return true by judging it's value is RunTime.
if (LicenseUsageMode.Designtime == LicenseManager.UsageMode) return false;
var procName = Process.GetCurrentProcess().ProcessName.ToLower();
return "devenv" != procName //WinForms app in VS IDE
&& "xdesproc" != procName //WPF app in VS IDE/Blend
&& "blend" != procName //WinForms app in Blend
//other IDE's process name if you detected by log from above
;
}
Attention!!!: The code returned bool is indicating NOT in design mode!
I wasn't able to get any of these solutions to work for me in Visual Studio 2019 when creating a WinForms app on .NET Core 3.1.
Both Appllication.ProcessName and Process.ProcessName are returning "DesignToolsServer" for me and LicenseManager.UsageMode returns LicenseUsageMode.Runtime when the Control is in another control or just on a form itself.
I did get it to work using Application.ProcessName == "DesignToolsServer".
Yes, you can check for whether you're in "design mode" from within an object's constructor. But using the WinForms DesignMode property doesn't always work as expected. An alternative:
This is my technique to check DesignMode in C# using Visual Studio and it does work in constructors.
// add this class...
public static class Globals
{
static Globals() => DesignMode = true;
public static bool DesignMode { get; set; }
}
// and modify your existing class...
public static class Program
{
public static void Main()
{
Globals.DesignMode = false;
// ...
// ... and then the rest of your program
//
// in any of your code you can check Globals.DesignMode for
// the information you want.
}
}
This solution is lightweight and simple. The downside is that you have to remember to clear the flag in your Main code.
When checking for "design mode," we're essentially checking for whether our code is being executed because our whole program is being run or because parts of our code are being executed by the VS designer. With this solution, the flag only gets set to false when the whole program is being run.
The LicenseManager solution does not work inside OnPaint, neither does this.DesignMode. I resorted to the same solution as #Jarek.
Here's the cached version:
private static bool? isDesignMode;
private static bool IsDesignMode()
{
if (isDesignMode == null)
isDesignMode = (Process.GetCurrentProcess().ProcessName.ToLower().Contains("devenv"));
return isDesignMode.Value;
}
Be aware this will fail if you're using any third party IDE or if Microsoft (or your end-user) decide to change the name of the VS executable to something other than 'devenv'. The failure rate will be very low, just make sure you deal with any resulting errors that might occur in the code that fails as a result of this and you'll be fine.
If you want to run some lines when it is running but not in the Visual Studio designer, you should implement the DesignMode property as follows:
// this code is in the Load of my UserControl
if (this.DesignMode == false)
{
// This will only run in run time, not in the designer.
this.getUserTypes();
this.getWarehouses();
this.getCompanies();
}
private void CtrlSearcher_Load(object sender, EventArgs e)
{
if(!this.DesignMode) InitCombos();
}
Timers that are enabled by default can cause crash when using custom/user controls. Disable them by default, and enable only after design mode check
public chartAdapter()
{
try
{
//Initialize components come here
InitializeComponent();
//Design mode check
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if (designMode)
return;
//Enable timers ONLY after designmode check, or else crash
timerAutoConnect.Enabled = timerDraw.Enabled = true;
I have a custom control which inherits from System.Web.UI.Control and some of its properties can be declaratively set using databinding expressions. e.g.
<foo:Foo runat="server" MyFoo="<%# this.GetFoo() %>" />
Now, when I do that I need to call .DataBind() on the control (or one of its parents) to evaluate these expressions.
What I would like to be able to do is detect if any properties were set this way and just automatically have the custom control call this.DataBind() after OnPreRender or there about.
So the question: how do I detect if databinding expressions are waiting to be executed?
I'm convinced that in some ControlBuilder or DataBindContext class lives the information needed to determine this. I've hunted around with Reflector and cannot seem to find it.
I should add, that I don't want to pay the overhead of executing DataBind() if no direct properties have been assigned this way. This is why I'd like to detect before hand. This class is extremely light but I'd like the ability to declaratively set properties without needing any code behind.
Doing some deeper looking into ControlBuilder, I noticed that the compiled factory for each control instance will attach a DataBinding event handler when there are data binding expressions present. I've found that checking for this seems to be a very reliable method for determining if data binding needs to occur. Here is the basis of my solution to the problem:
using System;
using System.Reflection;
using System.Web.UI;
public class AutoDataBindControl : Control
{
private static readonly object EventDataBinding;
private bool needsDataBinding = false;
static AutoDataBindControl()
{
try
{
FieldInfo field = typeof(Control).GetField(
"EventDataBinding",
BindingFlags.NonPublic|BindingFlags.Static);
if (field != null)
{
AutoDataBindControl.EventDataBinding = field.GetValue(null);
}
}
catch { }
if (AutoDataBindControl.EventDataBinding == null)
{
// effectively disables the auto-binding feature
AutoDataBindControl.EventDataBinding = new object();
}
}
protected override void DataBind(bool raiseOnDataBinding)
{
base.DataBind(raiseOnDataBinding);
// flag that databinding has taken place
this.needsDataBinding = false;
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
// check for the presence of DataBinding event handler
if (this.HasEvents())
{
EventHandler handler = this.Events[AutoDataBindControl.EventDataBinding] as EventHandler;
if (handler != null)
{
// flag that databinding is needed
this.needsDataBinding = true;
this.Page.PreRenderComplete += new EventHandler(this.OnPreRenderComplete);
}
}
}
void OnPreRenderComplete(object sender, EventArgs e)
{
// DataBind only if needed
if (this.needsDataBinding)
{
this.DataBind();
}
}
}
This solution disables itself if no DataBinding event handler is attached or if the control is manually data bound (directly or via a parent).
Note that most of this code is just jumping through hoops to be able to test for the existence of the event. The only reflection needed is a one-time lookup to get the object used as the key for EventDataBinding.
There is an internal ArrayList called SubBuilders on the ControlBuilder class. For each databinding expression TemplateParser enocunters, ProcessCodeBlock() adds a CodeBlockBuilder object with a BlockType property CodeBlockType.DataBinding to SubBuilders.
So if you can get a handle to the ControlBuilder you want, you should be able to reflectively iterate over SubBuilders and look for objects of type CodeBlockBuilder where BlockType == CodeBlockType.DataBinding.
Note of course this is all kinds of nasty and I'm really suspicious this is the best way to solve your core problem. If you take two steps back and look at the original problem, maybe post that on Stackoverflow instead - there's plenty of super-smart people who can help come up with a good solution.