Обнаружение режима конструктора из конструктора элемента управления



следуя этому вопросу, можно ли определить, находится ли он в режиме проектирования или выполнения из конструктора объекта?



Я понимаю, что это может быть невозможно, и что мне придется изменить то, что я хочу, но сейчас меня интересует этот конкретный вопрос.

505   11  

11 ответов:

можно использовать LicenceUsageMode перечисления в System.ComponentModel пространство имен:

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;

компонент ... насколько я знаю, не имеет свойства DesignMode. Это свойство обеспечивается контролем. Но проблема в том, что пользовательский элемент управления находится в форме в конструкторе, этот пользовательский элемент управления работает в режиме выполнения.

Я испытал, что свойство DesignMode работает правильно только по форме.

важно

есть разница в использовании Windows формы или WPF!!

у них разные дизайнеры и нужны различные проверки. Кроме того, это сложно, когда вы смешиваете формы и элементы управления WPF. (например, элементы управления WPF внутри окна форм)

если у вас есть Windows формы используйте этот:

Boolean isInWpfDesignerMode   = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);

если у вас только WPF используйте этот проверьте:

Boolean isInFormsDesignerMode = (System.Diagnostics.Process.GetCurrentProcess().ProcessName == "devenv");

если у вас смешанного использования форм и WPF, используйте проверку следующим образом:

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));

замечание:

вам нужно добавить пространства имен

вы должны использовать компонент.Свойство DesignMode. Насколько я знаю, это не должно использоваться из конструктора.

еще один интересный метод описан в этом блоге: http://www.undermyhat.org/blog/2009/07/in-depth-a-definitive-guide-to-net-user-controls-usage-mode-designmode-or-usermode/

в основном, он проверяет выполнение сборки, на которую статически ссылаются из сборки ввода. Он обходит необходимость отслеживать имена сборок ('devenv.exe', ' монодевелоп.exe'..).

, Он не работает во всех других сценариях, где сборка динамически загружается (VSTO является одним из примеров).

элементы управления (формы, UserControls и др.) наследовать Component class имеющего bool property DesignMode так:

if(DesignMode)
{
  //If in design mode
}

при сотрудничестве дизайнера... Его можно использовать в элементах управления, компонентах, во всех местах

    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 не работает внутри OnPaint, так же как и это.DesignMode. Я прибегнул к тому же решению, что и @Jarek.

вот кэшированная версия:

    private static bool? isDesignMode;
    private static bool IsDesignMode()
    {
        if (isDesignMode == null)
            isDesignMode = (Process.GetCurrentProcess().ProcessName.ToLower().Contains("devenv"));

        return isDesignMode.Value;
    }

имейте в виду, что это не удастся, если вы используете какую-либо стороннюю IDE или если Microsoft (или ваш конечный пользователь) решит изменить имя исполняемого файла VS на что-то другое, чем "devenv". Частота отказов будет очень низкой, просто убедитесь, что вы имеете дело с любыми результирующими ошибками, которые могут возникнуть в код, который не работает в результате этого, и вы будете в порядке.

Если вы хотите запустить некоторые строки, когда он работает, но не в конструкторе Visual Studio, необходимо реализовать свойство DesignMode следующим образом:

// 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();
}

Это метод, который я использовал в своем проекте:

//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:.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
        ;
}

внимание!!!: код, возвращенный bool указывает не в режиме конструктора!

Comments

    Ничего не найдено.