Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否在每次属性更改时使自定义控件无效?_C#_Winforms_Custom Controls - Fatal编程技术网

C# 是否在每次属性更改时使自定义控件无效?

C# 是否在每次属性更改时使自定义控件无效?,c#,winforms,custom-controls,C#,Winforms,Custom Controls,我正在开发一个自定义winforms控件,它公开了许多属性,这些属性会影响控件在背景、文本和悬停等不同状态下的不同颜色,单击以及图标等。对其中一个属性的更改需要重新绘制,因此此时每个属性都有一个getter和setter,setter调用Invalidate。这对代码来说是非常烦人的,如果同时更改多个属性,则每个属性都会导致重新绘制,即使最后重新绘制一次就足够了 我有以下想法,但我不知道它们是否可行或如何实施: 缓存属性更改几毫秒,然后失效 使用某种反射来检测调用方是否要在下一行中更改另一个属性

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

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

缓存属性更改几毫秒,然后失效 使用某种反射来检测调用方是否要在下一行中更改另一个属性,如果是,则延迟调用以使其无效 可能是属性之前的一些属性使重新绘制成为必要,或者是编译时扩展到getter/setter的所有此类属性的列表
如果这些想法有意义/可能,你能给我一些建议,并告诉我如何实施它们吗?

请注意,我不想使用选项2。关于选项1,在某种程度上,系统已经缓存了属性更改,只有在UI线程返回到处理消息时,它才会重新绘制。至于方案3,似乎有点牵扯其中

但是在回答你的问题时,最简单的方法是在你的类中创建一个计时器,在给定的时间间隔内启动。然后有一个bool,如果它为真,计时器的Tick处理程序将调用Invalidate并将其设置回false。最后,用一个方法来代替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,它应该可以工作。

如果同时更改多个属性??你指的是代码,不是用户?为此,可以使用Suspend/ResumeLayout,否?@TaW是的,我指的是代码。我不知道suspend/resumelayout,我会调查一下。谢谢谢谢,我将尝试此方法。在designer中删除控件时,这可能会导致竞争条件。