如何在自定义CF控件中覆盖Ambient BackColor

时间:2012-01-30 18:25:35

标签: .net visual-studio compact-framework custom-controls

我有一个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更改为Window。但随后设计器基础架构中的某些内容将颜色(通过属性)设置回Control。这发生在ctor之后但在OnResize和OnHandleCreated之前。现在,如果控件将BackColor属性序列化为具有正确值的设计器,则可以安全地设置它,但设计器不包含默认值。

最后一次编辑,我认为用于指定枚举(而不是基本类型)的默认值语法不正确。我正在使用我在下面发布的解决方案,但它是一个黑客,希望下一个人可以解决它真实。

1 个答案:

答案 0 :(得分:0)

我希望能得到一个真正的答案,但我会在这里提出我的解决办法:

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

}