【笔记】在WPF中PriorityBinding的详细介绍

  • PriorityBinding 用于"按优先级选择多个候选绑定中的第一个可用值"。当更高优先级的绑定后来变得可用时,目标会自动切换到它。
  • 典型场景:显示名优先级(DisplayName > UserName > Id)、慢源异步加载(先用本地缓存,后切到远程结果)。

一、核心功能

  • 选择策略:按 Bindings 顺序尝试,取第一个成功产生值的绑定。若其值变为不可用(UnsetValue/错误),会回退到下一个可用绑定;更高优先级绑定恢复可用时再切回。
  • 属性继承:继承 BindingBase 的能力(StringFormat、TargetNullValue、FallbackValue、Delay)。
  • 子绑定能力:每个子 Binding 可拥有自己的 Mode、UpdateSourceTrigger、Converter、Source/ElementName/RelativeSource、IsAsync 等。
  • 写回规则:TwoWay 写回时,只写回"当前生效"的子 Binding;若该子绑定是 OneWay 则无法写回。
  • 生存期:与普通绑定一致,支持通知更新;不与 MultiBinding 混用,它只选一个,不做合成。

二、使用方式

  1. 基础:优先显示 DisplayName,不存在则退到 UserName,再退到 Id
xaml 复制代码
<UserControl x:Class="H.Test.DataGrid.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel Margin="12" Orientation="Vertical" Spacing="6">
        <TextBlock>
            <TextBlock.Text>
                <PriorityBinding FallbackValue="(无)" StringFormat="显示名:{0}">
                    <Binding Path="DisplayName"/>
                    <Binding Path="UserName"/>
                    <Binding Path="Id"/>
                </PriorityBinding>
            </TextBlock.Text>
        </TextBlock>
    </StackPanel>
</UserControl>
  1. 与不同源组合:优先取另一个元素的值,其次取 DataContext 的属性
xaml 复制代码
<UserControl ...>
    <StackPanel Margin="12" Orientation="Vertical" Spacing="6">
        <TextBox x:Name="NameBox" Text="外部来源"/>
        <TextBlock>
            <TextBlock.Text>
                <PriorityBinding StringFormat="名称:{0}">
                    <!-- 先尝试来自元素 NameBox 的 Text -->
                    <Binding ElementName="NameBox" Path="Text"/>
                    <!-- 再尝试 VM 的属性 -->
                    <Binding Path="DisplayName"/>
                </PriorityBinding>
            </TextBlock.Text>
        </TextBlock>
    </StackPanel>
</UserControl>
  1. 异步慢源优先:高优先级远程值 IsAsync,加载前使用本地缓存,加载后自动切换
xaml 复制代码
<UserControl ...>
    <StackPanel Margin="12" Orientation="Vertical" Spacing="6">
        <TextBlock>
            <TextBlock.Text>
                <PriorityBinding StringFormat="价格:{0:C2}" FallbackValue="(加载中)">
                    <!-- 高优先级:远程价格,异步取值 -->
                    <Binding Path="RemotePrice" IsAsync="True"/>
                    <!-- 低优先级:本地缓存 -->
                    <Binding Path="CachedPrice"/>
                </PriorityBinding>
            </TextBlock.Text>
        </TextBlock>
    </StackPanel>
</UserControl>
  1. TwoWay 场景:仅当前生效的子绑定会被写回
xaml 复制代码
<UserControl ...>
    <StackPanel Margin="12" Orientation="Vertical" Spacing="6">
        <TextBox>
            <TextBox.Text>
                <PriorityBinding>
                    <!-- 若允许写回,请确保子绑定 Mode=TwoWay 且可写 -->
                    <Binding Path="EditableDisplayName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
                    <Binding Path="EditableUserName"   Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
                </PriorityBinding>
            </TextBox.Text>
        </TextBox>
    </StackPanel>
</UserControl>
  1. 简单 ViewModel(示例数据)
csharp 复制代码
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Controls;

namespace H.Test.DataGrid
{
    public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
            DataContext = new DemoVM
            {
                DisplayName = null,      // 故意置空以触发回退
                UserName = "Ada",
                Id = 1001,
                CachedPrice = 9.99m,
                RemotePrice = 0m // 假设后台异步更新该值,触发优先级切换
            };
        }
    }

    public sealed class DemoVM : INotifyPropertyChanged
    {
        private string? _displayName;
        private string _userName = "";
        private int _id;
        private decimal _cachedPrice;
        private decimal _remotePrice;
        private string _editableDisplayName = "";
        private string _editableUserName = "";

        public string? DisplayName { get => _displayName; set { _displayName = value; OnPropertyChanged(); } }
        public string  UserName    { get => _userName;    set { _userName    = value; OnPropertyChanged(); } }
        public int     Id          { get => _id;          set { _id          = value; OnPropertyChanged(); } }

        public decimal CachedPrice { get => _cachedPrice; set { _cachedPrice = value; OnPropertyChanged(); } }
        public decimal RemotePrice { get => _remotePrice; set { _remotePrice = value; OnPropertyChanged(); } }

        public string EditableDisplayName { get => _editableDisplayName; set { _editableDisplayName = value; OnPropertyChanged(); } }
        public string EditableUserName    { get => _editableUserName;    set { _editableUserName    = value; OnPropertyChanged(); } }

        public event PropertyChangedEventHandler? PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string? name = null)
            => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

三、实践要点与易错

  • 写回只针对当前激活的子绑定;如需编辑请确保该子绑定 Mode=TwoWay,且其源可写。
  • 与 MultiBinding 区分:PriorityBinding 不拼接值,仅选一个可用值;拼接请用 MultiBinding + StringFormat。
  • 可配合 StringFormat/TargetNullValue/FallbackValue 统一包装显示;以 "{" 开头的格式记得用前缀 "{}" 转义。
  • 异步慢源优先时,高优先级子绑定可设 IsAsync;当异步完成后,会从低优先级显示切换为高优先级结果。
  • 不要把"必须同时生效的多个值"放进 PriorityBinding------它只会选一个。

四、文档链接

了解更多

System.Windows.Controls 命名空间 | Microsoft Learn

控件库 - WPF .NET Framework | Microsoft Learn

WPF 介绍 | Microsoft Learn

使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn

https://github.com/HeBianGu

HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频

GitHub - HeBianGu/WPF-Control: WPF轻量控件和皮肤库

GitHub - HeBianGu/WPF-ControlBase: Wpf封装的自定义控件资源库

相关推荐
Honker_yhw2 小时前
大数据管理与应用系列丛书《数据挖掘》(吕欣等著)读书笔记-Logistic回归
笔记·学习
Brilliantwxx5 小时前
【C++】 继承与多态(中)
开发语言·c++·笔记·算法
MY_TEUCK11 小时前
【2026最新Python+AI学习基础】Python 入门笔记篇
笔记·python·学习
nnsix16 小时前
设计模式 - 模板方法模式 笔记
笔记·设计模式·模板方法模式
bugcome_com16 小时前
WPF + Prism 技术指南与实战项目(一、自行搭建)
wpf·prism
RainCity17 小时前
Java Swing 自定义组件库分享(六)
java·笔记·后端
羊群智妍18 小时前
2026 AI搜索优化:企业级GEO监测工具选型手册
笔记
x_yeyue20 小时前
2026第十七届蓝桥杯c++B组省赛题解
笔记·算法·蓝桥杯·acm·题解
一马平川的大草原20 小时前
报告笔记--AI工程的文化研读记录及感悟
人工智能·笔记·读书笔记