每个属性更改的Invalidate()自定义控件?

时间:2015-03-31 23:18:18

标签: c# winforms custom-controls

我正在开发一个自定义winforms控件,它暴露了很多影响控件外观的属性(背景,文本和不同状态的不同颜色,如悬停,点击以及图标等)。对其中一个属性的更改会使重绘成为必要,因此目前每个属性都有一个getter和setter,其setter调用Invalidate()。这对代码来说非常烦人,如果一次更改多个属性,即使最后一次重绘就足够了,每个属性都会导致重绘。

我有以下想法,但我不知道它们是否可行或如何实施:

  1. 缓存属性更改几毫秒,然后Invalidate()
  2. 使用某种反射来检测调用者是否要在下一行中更改另一个属性,如果是,则延迟调用Invalidate()
  3. 在进行必要重绘的属性之前可能有一些属性,或者在编译时扩展到getter / setter的所有此类属性的列表
  4. 如果这些想法有意义/有可能,你能给我一些建议,并指出如何实施它们吗?

1 个答案:

答案 0 :(得分:0)

只是注意,我将远离选项2.关于选项1,在某种程度上,系统已经缓存了属性更改,只有在UI线程返回处理消息后,它才会重绘。至于选项3,似乎有点参与。

但是在回答你的问题时,最简单的方法是在你的班级中创建一个以给定间隔触发的计时器。然后有一个bool,如果它是真的,计时器的Tick处理程序将调用Invalidate()并将其设置为false。最后制作一个方法,用来代替将该bool标记为真的Invalidate。

在您的情况下可能存在我不知道的危险,但这是一个例子:

public class InvalidationUserControl : UserControl
{
   bool _isInvalid = false;
   int _data;
   Timer t = new Timer();

   public InvalidationUserControl()
   {
      InitializeComponent();
      t.Interval = 100;  // Go ahead an play with this number, the higher
                         // it is the greater the latency
      t.Tick += t_Tick;
      t.Start();
   }

   void InvalidateIfNeeded()
   {
      _isInvalid = true;
   }

   void t_Tick(object sender, EventArgs e)
   {
      if (_isInvalid)
      {
          _isInvalid = false;
          Invalidate();
      }
   }

   public int Data
   {
       get { return _data; }
       set
       {
           _data = value;
           InvalidateIfNeeded();
       }
   }
}

可能有更好的方法,但这是一个快速的解决方案,可能完全按照你需要的方式工作。

您所要做的就是调用InvalidateIfNeeded()而不是Invalidate(),它应该可以工作。