延迟属性更新,直到一堆属性发生更改(即锁定控件)

发布于 2024-12-08 03:11:34 字数 498 浏览 1 评论 0原文

我制作了一个控件,该控件具有通过使用一些其他属性作为输入来计算的属性。当任何这些输入属性发生更改时,需要更新该属性。我已经通过为它们实现属性更改事件,将依赖属性标记为已更新,使这成为可能。更改 3 个属性意味着 3 次属性刷新。

我遇到的问题是,当多个属性发生更改时,每次更改其中任何一个属性时,依赖属性都会更新。然而,该属性需要一些时间来计算(和/或渲染)。当要更改多个属性时,我想让它在更新所有属性后仅更新一次。

目标:仅当程序完成更改所有属性时才需要更新控件。

我尝试过的方法:

  • 仅在请求时更新属性,从而使属性变得懒惰。 (不起作用,WPF 无论如何都要求它);
  • 缓存计算结果。 (不起作用,因为总是有 1 个输入发生变化,导致缓存无效);
  • 创建一个方法来一次设置多个属性。 (不起作用,有些属性是继承的并且来自另一个控件);
  • 在操作属性之前使控件折叠。 (不起作用,WPF仍然刷新属性)。

有人有更好的解决方案吗?

I have made a control which has a property that is calculated by using a few other properties as input. When any of these input properties change, the property needs to be updated. I already have made this possible through implementing property-changed events for them, marking the dependent property as updated. Changing 3 properties means 3 property refreshes.

The problem I am experiencing is that when more than one of these properties change, the dependency property is updated each time any of these properties is changed. The property however takes some time to calculate (and/or render). When more than one property is going to be changed, I would like to let it update only once, after I have updated all the properties.

Goal: The control needs to be updated only when the program is done changing all the properties.

What I have tried:

  • Make the property lazy by only updating it when requested. (Does not work, WPF requests it anyway);
  • Cache the result of the calculation. (Does not work because there is always 1 input changed, making the cache invalid);
  • Make a method to set multiple properties at once. (Does not work, some properties are inherited and come from another control);
  • Make the control collapsed before manipulating the properties. (Does not work, WPF still refreshes the properties).

Does anybody have a better solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半步萧音过轻尘 2024-12-15 03:11:34

您可以推迟引发属性更改事件。或者创建一个将停止传播此事件的方法(即 StartUpdating)和另一个将触发所有事件的方法(即 EndUpdating)。

private bool _isUpdating;
private List<string> _properties = ...;

private void RaisePropertyChanged(string propertyName)
{
   if(_isUpdating) 
   {
     if(!_properties.Contains(propertyName)) _properties.Add(propertyName);
     return;
   } 

   PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

void StartUpdating() { _isUpdating = true; }

void EndUpdating()
{
  _isUpdating = false;
  foreach(var propertyName in _properties) RaisePropertyChanged(propertyName);
}

并在你的方法中

void LongRunningMethodSync()
{
  try
  {
    StartUpdating(); 
    // do something synchronously
  }
  finally
  {
    EndUpdating();
  }
}

void LongRunningMethodAsync()
{
  StartUpdating(); 
  ExecuteMyAsyncTask(done => EndUpdating());
}

You can postpone raising the property changed event. Or create a method that will stop propagating this event (i.e. StartUpdating) and another method that will fire all the events (i.e. EndUpdating).

private bool _isUpdating;
private List<string> _properties = ...;

private void RaisePropertyChanged(string propertyName)
{
   if(_isUpdating) 
   {
     if(!_properties.Contains(propertyName)) _properties.Add(propertyName);
     return;
   } 

   PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

void StartUpdating() { _isUpdating = true; }

void EndUpdating()
{
  _isUpdating = false;
  foreach(var propertyName in _properties) RaisePropertyChanged(propertyName);
}

and in your methods

void LongRunningMethodSync()
{
  try
  {
    StartUpdating(); 
    // do something synchronously
  }
  finally
  {
    EndUpdating();
  }
}

void LongRunningMethodAsync()
{
  StartUpdating(); 
  ExecuteMyAsyncTask(done => EndUpdating());
}
柳若烟 2024-12-15 03:11:34

查看绑定的 IsAsync财产。我想它可以与 debounce 之类的模式结合使用。

Take a look at the binding's IsAsync property. I imagine it could work in combination with a debounce like pattern.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文