
WPFはコントロールのプロパティの一部をバックアップし、魔法の操作を行い、プロパティを復元します。なんと普通の操作でしょう!しかし、どのようにバックアップするかは研究に値する。直接割り当て?穴を踏んでいないからでしょう。
この記事の内容_
- シナリオと問題点
- 解決策と原理
- 延長する。
シナリオと問題点
ここで、(コーディングのために)シナリオを想像しましょう:
- いくつかのスタイル属性が設定されたウィンドウがあります
- このウィンドウをフルスクリーンに設定する必要があり、元のプロパティのいくつかを変更する必要があります(WPFにはバグがありますので、別のブログ記事を書きます)。
- ウィンドウの全画面設定を解除すると、以前に変更したプロパティは“完全に”復元されます。
通常はこう書かれる。
private Window _window;
private WindowStyle _oldStyle;
private void OnEnterFullScreen()
{
_oldStyle = _window.WindowStyle;
_window.WindowStyle = WindowStyle.None;
}
private void OnExitFullScreen()
{
_window.WindowStyle = _oldStyle;
}
しかしながら:
- 如果某人在
WindowStyle上设了个动态的样式怎么办?——那当然是不再动态了呀(因为覆盖了样式值) - 如果某人在
WindowStyle上设置了绑定怎么办?——那当然也是不再生效了呀(因为绑定被你覆盖了)
解決策と原理
因为各大 WPF 入门书籍都说到了 WPF 依赖项属性的优先级机制,所以大家应该基本都知道这个。不了解的,可以立刻去这里看看:依赖项属性值优先级 - WPF Microsoft Docs。
強制>アニメーション>ローカル値>テンプレート>暗黙のスタイル>スタイル·トリガー>テンプレート>テンプレート>テンプレート>スタイル·トリガー>デフォルト·スタイル>プロパティ継承>メタデータのデフォルト値の優先度です。
代わりに、XAMLまたはC#コードに直接代入することで、“ローカル値”を設定します。したがって、ローカル値が設定されている場合、優先度の低いスタイルは当然無効になります。
那么绑定呢?绑定在依赖项属性优先级中并不存在。绑定实际上是通过“本地值”来实现的,将一个绑定表达式设置到“本地值”中,然后在需要值的时候,会 ProvideValue 提供值。所以,如果再设置了本地值,那么绑定的设置就被覆盖掉了。
但是,SetCurrentValue 就是干这件事的!
SetCurrentValue 设计为在不改变依赖项属性任何已有值的情况下,设置属性当前的值。
_window.SetCurrentValue(Window.WindowStyleProperty, WindowStyle.None);
那么,只需要还原 SetCurrentValue 所做的修改,就还原了此依赖项属性的一切设置的值:
_window.InvalidateProperty(Window.WindowStyleProperty);
注意不是 ClearValue,那会清除本地值。
然而还差一点,绑定如果在你应用 SetCurrentValue 期间有改变,那么这次的赋值并不会让绑定立即生效,所以我们还需要手工再让绑定重新更新值:
BindingOperations.GetBindingExpression(_window, Window.WindowStyleProperty)?.UpdateTarget();
要約すると、この記事の最初のコードは次のように更新されます:
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();
}
延長する。
コードをもう少し一般的にする:
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();
}
この記事は頻繁に更新されますので、古い誤った知識の誤解を避け、より良い読書体験を得るために、元のhttps://blog.walterlv.com/post/change-and-restore-wpf-dependency-value-without-disabling-the-declared-use-of-the-property.htmlをお読みください。
如果你想持续阅读我的最新博客,请点击 RSS 订阅,或者前往 CSDN 关注我的主页。
知识共享许可协议本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (walter.lv@qq.com) 。