How to set and restore the values of WPF dependency properties while retaining all original style/binding and user setting values

How to set and restore the values of WPF dependency properties while retaining all original style/binding and user setting values

WPF backs up some properties of a control, does some magic operations, and then restores these properties.

最后更新 11/9/2021 10:08 AM
吕毅
预计阅读 4 分钟
分类
WPF
标签
.NET WPF

WPF backs up some properties of a control, does some magic operations, and then restores these properties. What a common operation! However, how to back up is a question worth studying. Direct assignment? That must be because you didn't step in some pits.

Content of this article

  • Scenarios and issues
  • Solutions and principles
  • extending

Scenarios and issues

Now, let's imagine a scenario (for the convenience of coding):

  1. There is a window with some style properties set
  2. Now you need to set this window to full-screen, which requires modification of some original properties (there is a bug in the setting that comes with WPF, so I will write a separate blog explanation)
  3. After canceling the setting window full screen, those previously modified properties must be restored "perfectly"

Generally, you might write like this:

private Window _window;
private WindowStyle _oldStyle;

private void OnEnterFullScreen()
{
    _oldStyle = _window.WindowStyle;
    _window.WindowStyle = WindowStyle.None;
}

private void OnExitFullScreen()
{
    _window.WindowStyle = _oldStyle;
}

However:

  • 如果某人在 WindowStyle 上设了个动态的样式怎么办?——那当然是不再动态了呀(因为覆盖了样式值)
  • 如果某人在 WindowStyle 上设置了绑定怎么办?——那当然也是不再生效了呀(因为绑定被你覆盖了)

Solutions and principles

因为各大 WPF 入门书籍都说到了 WPF 依赖项属性的优先级机制,所以大家应该基本都知道这个。不了解的,可以立刻去这里看看:依赖项属性值优先级 - WPF Microsoft Docs

The priority is as follows: Mandatory> Animation> Local Values> Templates> Implicit Styles> Style Triggers> Template Triggers> Styles> Default Styles> Property Inheritance> Metadata Default Values.

Instead, we set the "local value" by assigning values directly in XAML or C#code. Therefore, if a local value is set, all lower-priority styles will of course be invalid.

那么绑定呢?绑定在依赖项属性优先级中并不存在。绑定实际上是通过“本地值”来实现的,将一个绑定表达式设置到“本地值”中,然后在需要值的时候,会 ProvideValue 提供值。所以,如果再设置了本地值,那么绑定的设置就被覆盖掉了。

但是,SetCurrentValue 就是干这件事的!

SetCurrentValue 设计为在不改变依赖项属性任何已有值的情况下,设置属性当前的值。

_window.SetCurrentValue(Window.WindowStyleProperty, WindowStyle.None);

那么,只需要还原 SetCurrentValue 所做的修改,就还原了此依赖项属性的一切设置的值:

_window.InvalidateProperty(Window.WindowStyleProperty);

注意不是 ClearValue,那会清除本地值。

然而还差一点,绑定如果在你应用 SetCurrentValue 期间有改变,那么这次的赋值并不会让绑定立即生效,所以我们还需要手工再让绑定重新更新值:

BindingOperations.GetBindingExpression(_window, Window.WindowStyleProperty)?.UpdateTarget();

So, in summary, the code at the beginning of this article will be updated to the following form:

private Window _window;

private void OnEnterFullScreen()
{
    _window.SetCurrentValue(Window.WindowStyleProperty, WindowStyle.None);
}

private void OnExitFullScreen()
{
    _window.InvalidateProperty(Window.WindowStyleProperty);
    BindingOperations.GetBindingExpression(_window, Window.WindowStyleProperty)?.UpdateTarget();
}

extending

Make the code more generic:

static void ApplyTempProperty(DependencyObject d, DependencyProperty dp, object tempValue)
{
    d?.SetCurrentValue(dp, tempValue);
}

static void RestoreProperty(DependencyObject d, DependencyProperty dp)
{
    d.InvalidateProperty(dp);
    BindingOperations.GetBindingExpression(d, dp)?.UpdateTarget();
}

This article will be updated frequently. Please read the original: https://blog.walterlv.com/post/change-and-restore-wpf-dependency-value-without-disabling-the-declared-use-of-the-property.html to avoid misleading by old erroneous knowledge and have a better reading experience.

如果你想持续阅读我的最新博客,请点击 RSS 订阅,或者前往 CSDN 关注我的主页

知识共享许可协议本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com)

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 9/13/2025

Migration from WPF to Avalonia series: Why I have to migrate WPF programs to Avalonia

In the past few years, our host computer software has been mainly developed using WPF and WinForm. These technologies are really easy to use on the Windows platform, and they have also accompanied us through the stage of small-scale trial production to today's large-scale delivery. However, with the development of business and changes in customer needs, the single Windows technology stack has gradually become a hurdle that we must overcome.

继续阅读
同分类 / 同标签 1/26/2025

WPF internationalizes with custom XML files

This article describes in detail the methods of using custom XML files to achieve internationalization in WPF programs, including installing the necessary NuGet package, dynamically obtaining language lists, dynamically switching languages, using translation strings in code and xaml interfaces, etc. It also provides source code links to help developers easily internationalize WPF applications.

继续阅读