Как переопределить Ambient BackColor в пользовательском элементе управления CF - PullRequest
3 голосов
/ 30 января 2012

У меня есть элемент управления Compact Framework (3.5), и мне бы хотелось, чтобы у него был цвет по умолчанию SystemColors.Window, по внешнему виду похожий на элемент управления для редактирования.Проблема, с которой я сталкиваюсь, заключается в том, что Visual Studio (2008) всегда отображает этот элемент управления в области дизайна со значением по умолчанию BackColor, равным Control.Я предполагаю, что он либо вытягивает его из цвета по умолчанию основы Control, из родительского элемента, либо из Site.

Кто-нибудь знает, как указать или иным образом сообщить Visual Studio, какой должен быть BackColor по умолчанию?

public class MoneyInput : Control
{

    public MoneyInput()
    {            
        base.BackColor = SystemColors.Window;
        base.ForeColor = SystemColors.WindowText;
    }

    public override Color BackColor
    {
        get
        {
            return base.BackColor;
        }
        set
        {
            base.BackColor = value;
            Repaint();                
        }
    }

}

А вот соответствующий раздел моего файла DesignTimeAttributes.xmta.Обратите внимание, что я не хочу, чтобы цвет по умолчанию был белым, как вы видите ниже, я просто пытался заставить что-нибудь работать:

<DesktopCompatible>true</DesktopCompatible>

<Property Name="BackColor">

  <Browsable>true</Browsable>

  <DesignerSerializationVisibility>
    DesignerSerializationVisibility.Visible
  </DesignerSerializationVisibility>

  <DefaultValue>
    <Type>System.Drawing.Color</Type>
    <Value>System.Drawing.Color.White</Value>
  </DefaultValue>

  <Category>Appearance</Category>

  <Description>The background color of the control</Description>

</Property>

Просто чтобы добавить еще какой-то прогресс (или его отсутствие), я добавил журнал к элементу управления, чтобы видеть, что происходит, когда я опускаю элемент управления на поверхность конструктора.Запись в BackColor в конструкторе вступает в силу и меняет цвет с элемента управления на окно.Но затем что-то в инфраструктуре дизайнера устанавливает цвет (через свойство) обратно в Control.Это происходит после ctor, но до OnResize и OnHandleCreated.Теперь, если элемент управления сериализует свойство BackColor в конструкторе с правильным значением, тогда оно будет безопасно возвращено, но конструктор не содержит значений по умолчанию.

Последнее редактирование, я думаю, что синтаксис значений по умолчанию для указания перечисления (в отличие от базового типа) является неправильным.Я использую решение, которое я разместил ниже, но это взлом, и, надеюсь, следующий человек, который придет, сможет решить его по-настоящему.

1 Ответ

0 голосов
/ 01 февраля 2012

Я надеюсь получить реальный ответ, но я опущу здесь мое решение для обходного пути:

public class MoneyInput : Control 
{

  // workaround for colors
  private bool _constructed = false;
  private int _handlesCreated; 


  public MoneyInput()
  {
      this.BackColor = SystemColors.Window;
      this.ForeColor = SystemColors.WindowText;
      _constructed = true;
  }

  public override Color BackColor
  {
      get
      {
          return base.BackColor;
      }
      set
      {
          // The logic below is based on:
          //
          // 1.  If not _constructed then we are getting called 
          //      from our ctor and we want the set to happen.
          // 2.  If we do not have a Handle yet then we are 
          //        getting called by the infrastructure that
          //        creates a control.  
          // 3.  At design-time, the VS designer applies the
          //        Ambient color even if we explicitly set 
          //        our own color.  It is supposed to only apply
          //        the Ambient if we have not explictly set
          //        a color.
          // 4.  At runtime we must accept any color changes
          //        that are passed to us.


          // see if VS designer is screwing with us
          bool ignoreColorSet =
              _constructed
              && _handlesCreated == 0
              && RunningInDesigner;


          if (!ignoreColorSet)
          {
              base.BackColor = value;
              Repaint();
          }


      }
  }


  protected override void OnHandleCreated(EventArgs e)
  {
      _handlesCreated++;
      base.OnHandleCreated(e);         
  }

  private bool RunningInDesigner
  {
      get
      {
          // this control is mobile-only so if we are running on full
          //  windows we must be in design mode.  Note that this works
          //  even if we are not Sited yet, where as checking the 
          //  DesignMode property can't be done untl the control has
          //  a Site.
          return (System.Environment.OSVersion.Platform == PlatformID.Win32NT
              || System.Environment.OSVersion.Platform == PlatformID.Win32Windows);
      }
  }

}     
...