नेस्टेड नियंत्रण के साथ DesignMode


87

क्या किसी ने नियंत्रण विकसित करते समय DesignMode समस्या का एक उपयोगी समाधान पाया है?

मुद्दा यह है कि यदि आप घोंसला नियंत्रित करते हैं तो DesignMode केवल पहले स्तर के लिए काम करता है। दूसरा और निचला स्तर DesignMode हमेशा FALSE लौटाएगा।

मानक हैक उस प्रक्रिया के नाम को देखने के लिए किया गया है जो चल रहा है और यदि यह "DevEnv.EXE" है तो इसे स्टूडियो होना चाहिए इसलिए DesignMode वास्तव में TRUE है।

उस समस्या के साथ जो ProcessName की तलाश कर रहा है वह रजिस्ट्री और अन्य अजीब भागों के माध्यम से अंतिम परिणाम के साथ अपने तरीके से काम करता है ताकि उपयोगकर्ता को प्रक्रिया का नाम देखने के लिए आवश्यक अधिकार न हो। इसके अलावा यह अजीब मार्ग बहुत धीमा है। इसलिए हमें एक सिंगलटन का उपयोग करने के लिए अतिरिक्त हैक करने के लिए ढेर करना पड़ा है और यदि प्रक्रिया का नाम पूछते समय कोई त्रुटि होती है, तो मान लें कि DesignMode FALSE है।

DesignMode को निर्धारित करने का एक अच्छा साफ तरीका क्रम में है। Microsoft को फ्रेमवर्क में आंतरिक रूप से इसे ठीक करने के लिए प्राप्त करना और भी बेहतर होगा!



8
+1 के लिए "Microsoft को आंतरिक रूप से इसे फ्रेमवर्क में ठीक करने के लिए प्राप्त करना बेहतर होगा" - किसी के समय के दस मिनट दसियों हज़ार लोगों को एक टुकड़ा बचाएंगे। यदि कोई ऐसा प्रोग्राम है जो बग पर निर्भर करता है और 100,000 जो इसके द्वारा असुविधाजनक हैं, तो यह एक प्रोग्राम को असुविधाजनक करने से बचने के लिए बग को रखने का कोई मतलब नहीं है!
ब्लूराजा - डैनी पफ्लुघोफ्ट

नमस्ते, यह 2008 में पोस्ट किया गया था। क्या अब यह तय हो गया है?
जेक

वीएस 2012 में यह अब भी वही है
बूगीयर

1
ध्यान दें कि अगर कोई UserControl के लिए कस्टम डिज़ाइनर का उपयोग कर रहा है (जैसे कि मैंने ControlDesigner से प्राप्त एक क्लास के साथ परीक्षण किया है), तो EnableDesignMode (सबकंट्रोल) को कॉल करने से लगता है कि उपमहाद्वीप कार्य की DesignMode प्रॉपर्टी है। यह समस्या का एक प्रभावी समाधान नहीं है, हालांकि हम हमेशा कंटेनर को नियंत्रित नहीं करते हैं जो हमारे नियंत्रण में है।
प्रोटानगुन

जवाबों:


80

इस प्रश्न का उत्तर देते हुए, मैंने अब इसे करने के 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 (विनफॉर्म एप्लिकेशन),
  • SubControl (dll)
  • SubSubControl (dll)

मैंने फिर SubControl में SubSubControl को एम्बेड किया, फिर TestApp.Form में प्रत्येक में से एक।

यह स्क्रीनशॉट रन करते समय परिणाम दिखाता है। रनिंग का स्क्रीनशॉट

यह स्क्रीनशॉट विजुअल स्टूडियो में खुले फॉर्म के साथ परिणाम दिखाता है:

न चलने का स्क्रीनशॉट

निष्कर्ष: ऐसा प्रतीत होता है कि केवल एक ही प्रतिबिंब के बिना जो निर्माणकर्ता के भीतर विश्वसनीय है, वह है लाइसेंसयूजेज, और केवल एक जो निर्माणकर्ता के बाहर विश्वसनीय है वह है 'IsDesignedHosted' ( नीचे BlueRaja द्वारा )

पुनश्च: नीचे टूलमेकरसैट की टिप्पणी देखें (जो मैंने परीक्षण नहीं किया है): "ध्यान दें कि IsDesignerHosted उत्तर को लाइसेंस यूजेज में शामिल करने के लिए अपडेट किया गया है ..., इसलिए अब परीक्षण बस हो सकता है अगर (IsDesignerHosted)। एक वैकल्पिक दृष्टिकोण है , निर्माता में परीक्षण लाइसेंस प्रबंधक। और परिणाम को कैश करें । "


@Benjol: IsDesignerHosted (नीचे) के बारे में क्या? (इसके अलावा, मुझे लगता है कि आपके पास डिज़ाइन-टाइम और रनटाइम स्वैप किया गया है, रनटाइम के दौरान इसे क्या कहते हैं, इसकी जांच करें)
ब्लूराजा - डैनी पफ्लुघोफ्ट

@BlueRaja, मेरे पास अभी भी वह परियोजना डिस्क पर कहीं न कहीं पड़ी है, शायद मुझे इसे कहीं पोस्ट करना चाहिए ...
बेंजोल

1
अनुभवजन्य प्रयोग द्वारा स्पष्टीकरण के लिए +1। @ बैंजोल, यदि आपको इसे फिर से देखने का मौका मिलता है, तो आप स्वयं ही मूल्यों के लिए एक मामला जोड़ सकते हैं क्योंकि बाल नियंत्रण को डिजाइनर में वास्तव में संपादित किए जा रहे वर्ग की तुलना में अलग तरीके से व्यवहार किया जा सकता है। (ध्यान दें कि संपादित किए जा रहे वर्ग के निर्माता को डिज़ाइनर में निष्पादित नहीं किया जाता है।)
रोब पार्कर

2
तो, प्रतिबिंब के बिना if(LicenseUseage == LicenseUsageMode.Designtime || IsDesignerHosted)100% सही दृष्टिकोण होगा?
स्कॉट चैंबरलेन

1
ध्यान दें कि IsDesignerHosted उत्तर को शामिल करने के लिए अपडेट किया गया है LicenseUsage..., इसलिए अब परीक्षण बस हो सकता है if (IsDesignerHosted)। एक वैकल्पिक दृष्टिकोण है , निर्माता में लाइसेंसधारक का परीक्षण और परिणाम को कैश करें
टूलमेकर

32

से यह पेज :

( [संपादित करें २०१३] निर्माणकर्ताओं में काम करने के लिए संपादित, @hopla द्वारा प्रदान की गई विधि का उपयोग करके)

/// <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 http://stackoverflow.com/a/2693338/238419 )
/// </summary>
public bool IsDesignerHosted
{
    get
    {
        if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
            return true;

        Control ctrl = this;
        while (ctrl != null)
        {
            if ((ctrl.Site != null) && ctrl.Site.DesignMode)
                return true;
            ctrl = ctrl.Parent;
        }
        return false;
    }
}

मैंने Microsoft के साथ बग-रिपोर्ट प्रस्तुत की है ; मुझे संदेह है कि यह कहीं भी जाएगा, लेकिन इसे वैसे भी वोट दें, क्योंकि यह स्पष्ट रूप से एक बग है (चाहे "डिजाइन द्वारा" हो या नहीं )।


29

आप लाइसेंस प्रबंधक की जाँच क्यों नहीं करते हैं। UMageMode इस गुण के मान हो सकते हैं लाइसेंसUsageMode.Runtime या लाइसेंसUsageMode.Designtime।

क्या आप कोड केवल रनटाइम में चलाना चाहते हैं, निम्न कोड का उपयोग करें:

if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
{
  bla bla bla...
}

8
+1 मैंने इसका भी उपयोग किया है। लोगों को कौन सी यात्राएं करना है कि DesignMode एक निर्माता में काम नहीं करेगा।
निकोलस पियासेकी

1
@ निकोलस: यह बाल नियंत्रण में भी काम नहीं करता है। यह बस टूट गया है।
ब्लूराजा - डैनी पफ्लुघोफ्ट

+1 - यह व्युत्पन्न नियंत्रण के डिजाइन के दौरान निर्मित किए जा रहे आधार नियंत्रणों पर भी काम करता है।
mcw

7

यह वह विधि है जिसका मैं अंदर के रूपों में उपयोग करता हूं:

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

इस तरह, परिणाम सही होगा, भले ही DesignMode या लाइसेंस प्रबंधक गुण विफल हो।


1
हां, यह आपके कहे अनुसार रूपों में काम करेगा। लेकिन मैं यह बताना चाहूंगा कि पोते के यूजर कंट्रोल में कंस्ट्रक्टर के बाहर काम नहीं होता है।
ऐलो सेप

5

मैं लाइसेंस प्रबंधक विधि का उपयोग करता हूं, लेकिन जीवन भर के उपयोग के लिए निर्माणकर्ता से मूल्य को कैश करता हूं।

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

1
जोनाथन, मैंने आपके उत्तर के लिए एक परीक्षण (परीक्षण) वीबी संस्करण जोड़ा है।
टूलमेकरसैट

3

हम इस कोड का उपयोग सफलता के साथ करते हैं:

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";
  }
}

3

मेरा सुझाव @ blueraja-danny-pflughoeft उत्तर का अनुकूलन है । यह समाधान हर बार परिणाम की गणना नहीं करता है, लेकिन केवल पहली बार में (कोई वस्तु उपयोग नहीं बदल सकती है। डिजाइन से रनटाइम तक)

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

यदि आप किसी मूल्य को कैश करने जा रहे हैं, तो इस जटिलता में जाने का कोई कारण नहीं है। इसके बजाय, जोनाथन के उत्तर का उपयोग करें , जो परिणाम को वर्गीकृत करते हुए, कंस्ट्रक्टर में सरल लाइसेंस प्रबंधक परीक्षण का उपयोग करता है ।
टूलमेकर

मुझे लगता है कि इस पद्धति का लाभ यह है, कि इसके लिए लाइसेंसरमैनेजर टेस्ट की भी आवश्यकता नहीं है, अगर किसी मामले में संपत्ति की कभी जरूरत नहीं होती है।
सेबेस्टियन वर्कर

2

मैं कभी भी खुद से पकड़ा नहीं गया है, लेकिन क्या आप नियंत्रण श्रृंखला से मूल श्रृंखला को वापस चलने के लिए नहीं देख सकते हैं कि क्या DesignMode आपके ऊपर कहीं सेट है?


2

चूंकि कोई भी विधि विश्वसनीय नहीं है (DesignMode, लाइसेंस प्रबंधक) या कुशल (प्रक्रिया, पुनरावर्ती चेक) मैं public static bool Runtime { get; private set }प्रोग्राम स्तर पर उपयोग कर रहा हूं और स्पष्ट रूप से इसे मुख्य () विधि के अंदर सेट कर रहा हूं ।


1

DesignMode एक निजी संपत्ति है (जो मैं बता सकता हूं) से। इसका जवाब सार्वजनिक संपत्ति प्रदान करना है जो DesignMode प्रोप को उजागर करता है। तब तक आप उपयोगकर्ता नियंत्रण की श्रृंखला का समर्थन कर सकते हैं जब तक कि आप एक गैर-उपयोगकर्ता नियंत्रण या एक नियंत्रण जो कि डिज़ाइन मोड में है, तब तक चलाएं। कुछ इस तरह....

  public bool RealDesignMode()
  {
     if (Parent is MyBaseUserControl)
     {
        return (DesignMode ? true : (MyBaseUserControl) Parent.RealDesignMode;
     }

     return DesignMode;
  }

जहाँ आपके सभी UserControls को MyBaseUserControl से विरासत में मिला है। वैकल्पिक रूप से आप एक इंटरफ़ेस लागू कर सकते हैं जो "RealDeisgnMode" को उजागर करता है।

कृपया ध्यान दें कि यह कोड लाइव कोड नहीं है। :)


1

मुझे एहसास नहीं था कि आप Parent.DesignMode को कॉल नहीं कर सकते हैं (और मैंने C # में 'संरक्षित' के बारे में कुछ सीखा है ...)

यहाँ एक चिंतनशील संस्करण है: (मुझे संदेह है कि डिजाइन बनाने के लिए एक प्रदर्शन लाभ हो सकता है।

static bool IsDesignMode(Control control)
{
    PropertyInfo designModeProperty = typeof(Component).
      GetProperty("DesignMode", BindingFlags.Instance | BindingFlags.NonPublic);

    while (designModeProperty != null && control != null)
    {
        if((bool)designModeProperty.GetValue(control, null))
        {
            return true;
        }
        control = control.Parent;
    }
    return false;
}

0

नेस्टेड यूज़रकंट्रोल का उपयोग करते समय मुझे हाल ही में विजुअल स्टूडियो 2017 में इस समस्या से जूझना पड़ा। मैं ऊपर और अन्य जगहों पर वर्णित दृष्टिकोणों में से कई को संयोजित करता हूं, फिर कोड को तब तक टाल दिया जाता है जब तक मेरे पास एक सभ्य विस्तार विधि नहीं थी जो अब तक स्वीकार्य रूप से काम करता है। यह चेक का एक क्रम करता है, जिसके परिणामस्वरूप स्टूल बूलियन वेरिएबल्स में परिणाम होता है इसलिए प्रत्येक चेक केवल रन टाइम के दौरान केवल एक बार ही किया जाता है। प्रक्रिया ओवरकिल हो सकती है, लेकिन यह कोड को स्टूडियो में निष्पादित करने से रोक रही है। आशा है कि यह किसी की मदद करता है।

  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;
  }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.