
Backing up some properties of a WPF control, performing some magical operations, and then restoring these properties. How common an operation! Yet, how to back them up is a question worth studying. Direct assignment? You must not have encountered certain pitfalls.
Contents
- Scenario and Problem
- Solution and Principle
- Extension
Scenario and Problem
Now, let's imagine a scenario (for coding convenience):
- There is a window with some style properties set.
- Now, the window needs to be set to full screen, which requires modifying some original properties (the built-in setting in WPF has bugs; I'll write another blog to explain).
- After exiting full screen, those modified properties must be "perfectly" restored.
A common way to write this might be:
private Window _window;
private WindowStyle _oldStyle;
private void OnEnterFullScreen()
{
_oldStyle = _window.WindowStyle;
_window.WindowStyle = WindowStyle.None;
}
private void OnExitFullScreen()
{
_window.WindowStyle = _oldStyle;
}
However:
- What if someone has set a dynamic style on
WindowStyle? — Then it will no longer be dynamic (because the style value is overwritten). - What if someone has set a binding on
WindowStyle? — Then it will no longer take effect (because the binding is overwritten by you).
Solution and Principle
Since many introductory WPF books mention the precedence mechanism of dependency properties, you should basically know about it. If you don't, go here immediately: Dependency Property Value Precedence - WPF Microsoft Docs.
The precedence is: Coercion > Animations > Local Value > Template > Implicit Style > Style Triggers > Template Triggers > Style > Default Style > Property Value Inheritance > Metadata Default.
When you assign a value directly in XAML or C# code, you are setting a "local value". Therefore, if a local value is set, all lower-priority styles naturally become invalid.
What about bindings? Bindings do not exist in the dependency property priority list. Bindings are actually implemented through "local values": a binding expression is set into the local value, and when the value is needed, ProvideValue provides it. So, if you set a local value again, the binding's setting is overwritten.
But SetCurrentValue is exactly designed for this!
SetCurrentValue is designed to set the current value of a property without changing any existing value of the dependency property.
_window.SetCurrentValue(Window.WindowStyleProperty, WindowStyle.None);
Then, to revert the changes made by SetCurrentValue, you can restore all set values of this dependency property:
_window.InvalidateProperty(Window.WindowStyleProperty);
Note that it's not ClearValue, which clears the local value.
However, one more thing: if the binding changes while you apply SetCurrentValue, the assignment will not make the binding take effect immediately, so you need to manually force the binding to update its value:
BindingOperations.GetBindingExpression(_window, Window.WindowStyleProperty)?.UpdateTarget();
Therefore, combining everything, the initial code will be updated to:
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();
}
Extension
To 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 article: https://blog.walterlv.com/post/change-and-restore-wpf-dependency-value-without-disabling-the-declared-use-of-the-property.html to avoid misleading from outdated and incorrect knowledge, and to have a better reading experience.
If you want to keep reading my latest blog, please click RSS subscription, or go to CSDN to follow my homepage.
Creative Commons License This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. You are free to share, adapt, and republish, but must retain the author's attribution (Lü Yi, including link: https://blog.walterlv.com ), not for commercial purposes, and must distribute any modifications under the same license. If you have any questions, please contact me (walter.lv@qq.com).