【问题标题】:Invalidate() custom control on every property change?Invalidate() 对每个属性更改的自定义控件?
【发布时间】:2015-03-31 23:18:17
【问题描述】:

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

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

  1. 缓存属性更改几毫秒,然后Invalidate()
  2. 使用某种反射来检测调用者是否要更改下一行中的另一个属性,如果是,则延迟调用Invalidate()
  3. 可能是在需要重绘的属性之前的一些属性,或者是在编译时扩展为 getter/setter 的所有此类属性的列表

如果这些想法有意义/可行,您能否给我一些建议,并指出如何实施它们?

【问题讨论】:

  • 如果同时更改多个属性, ??你的意思是代码,而不是用户?为此可以使用 Suspend/ResumeLayout,不是吗?
  • @TaW 是的,我的意思是代码。我不知道暂停/恢复布局,我会调查的。谢谢!

标签: c# winforms custom-controls


【解决方案1】:

请注意,我会远离选项 2。关于选项 1,在某种程度上,系统已经缓存了属性更改,只有在 UI 线程返回处理消息时才会重绘。至于方案三,好像有点牵扯。

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

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

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(),它应该可以工作。

【讨论】:

  • 谢谢,我试试看
  • 这可能会导致在设计器中删除控件时出现争用情况。
猜你喜欢
  • 1970-01-01
  • 2018-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
相关资源
最近更新 更多