元のスタイル/バインディングとユーザー設定値をすべて保持したまま、WPF依存関係プロパティの値を設定および復元する方法

元のスタイル/バインディングとユーザー設定値をすべて保持したまま、WPF依存関係プロパティの値を設定および復元する方法

WPFはコントロールのプロパティの一部をバックアップし、魔法の操作を行い、プロパティを復元します。

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

WPFはコントロールのプロパティの一部をバックアップし、魔法の操作を行い、プロパティを復元します。なんと普通の操作でしょう!しかし、どのようにバックアップするかは研究に値する。直接割り当て?穴を踏んでいないからでしょう。

この記事の内容_

  • シナリオと問題点
  • 解決策と原理
  • 延長する。

シナリオと問題点

ここで、(コーディングのために)シナリオを想像しましょう:

  1. いくつかのスタイル属性が設定されたウィンドウがあります
  2. このウィンドウをフルスクリーンに設定する必要があり、元のプロパティのいくつかを変更する必要があります(WPFにはバグがありますので、別のブログ記事を書きます)。
  3. ウィンドウの全画面設定を解除すると、以前に変更したプロパティは“完全に”復元されます。

通常はこう書かれる。

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)

Keep Exploring

延伸阅读

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

WPFからAvaloniaへの移行シリーズ:WPFプログラムをAvaloniaに移行する必要がある理由

ここ数年、当社のホストソフトウェアは主にWPFとWin Formで開発されてきました。これらのテクノロジーはWindowsプラットフォームで非常にうまく機能し、小規模なパイロット生産から今日の大規模なデリバリまでの段階を経てきました。しかし、ビジネスの成長と顧客のニーズの変化に伴い、単一のWindowsテクノロジースタックは私たちが乗り越えなければならないハードルになりました。

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

WPFはカスタムXMLファイルで国際化を実現

この記事では、必要なNuGetパッケージのインストール、言語リストの動的取得、言語の動的切り替え、コードとxamlインターフェイスでの翻訳文字列の使用、開発者がWPFアプリケーションを簡単に国際化できるようにするソースコードへのリンクなど、WPFプログラムでカスタムXMLファイルを使用した国際化の方法について詳しく説明します。

继续阅读