WPF数据绑定

数据绑定是一个很强大且优雅的技能,之前用过好多次,但有些地方总不是特别清晰,常常需要重新翻阅资料来回顾,于是这次用了几天时间好好梳理一下,记录一下。

首先数据绑定对数据对象的要求:需要是公有属性(不支持字段和私有属性)。

如果需要在数据内容发生变化时自动更新到控件,则需要实现INotifyPropertyChanged接口,其包含 PropertyChanged事件,在属性变化时引发PropertyChanged事件。

如果绑定对象为集合时,需要在集合内容发生变化时自动更新到控件,则需要INotifyCollectionChanged接口,其包含CollectionChanged事件,目前内置的泛型集合 ObservableCollection 实现了该接口。

通常在设置绑定时,我们需要指定数据上下文,DataContext,如果控件没有设置DataContext,则会去找父容器的DataContext,依层级依次查找。也有些控件直接在代码中指定ItemsSource的。如果要绑定的数据依赖于另外一个控件的值,可以在DataContext中,绑定到另外一个控件的选中项,然后设置该控件的数据源或者绑定值。

MainWindow.xaml

cs 复制代码
<Window x:Class="TestBinding.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestBinding"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <StackPanel Name="parentContainer">
        <StackPanel Orientation="Horizontal">
            <TextBlock>BindData:</TextBlock>
            <TextBox Text="{Binding Path=BindData}"></TextBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal">
            <TextBlock>BindDatas:</TextBlock>
            <ListBox Name="exchangeListBox" ItemsSource="{Binding Path=Exchanges}" DisplayMemberPath="ExchangeID"></ListBox>
        </StackPanel>
        <StackPanel>
            <ComboBox Name="instrumentCombbox" DataContext="{Binding ElementName=exchangeListBox, Path=SelectedItem}" ItemsSource="{Binding Path=Instruments}" DisplayMemberPath="InstrumentID"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=instrumentCombbox, Path=SelectedItem}">
            <TextBlock>ExchangeID:</TextBlock>
            <TextBox Text="{Binding Path=ExchangeID}"></TextBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=instrumentCombbox, Path=SelectedItem}">
            <TextBlock>InstrumentID:</TextBlock>
            <TextBox Text="{Binding Path=InstrumentID}"></TextBox>
        </StackPanel>
        <StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=instrumentCombbox, Path=SelectedItem}">
            <TextBlock>InstrumentName:</TextBlock>
            <TextBox Text="{Binding Path=InstrumentName}"></TextBox>
        </StackPanel>
    </StackPanel>
</Window>

MainWindow.xaml.cs

cs 复制代码
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace TestBinding;

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    protected virtual bool SetProperty<T>(ref T member, T value, [CallerMemberName] string? propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(member, value))
        {
            return false;
        }
        member = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}
public class ExchangeViewModel : ViewModelBase
{
    private string exchangeID = string.Empty;
    public string ExchangeID { get => exchangeID; set => SetProperty(ref exchangeID, value); }
    public ObservableCollection<InstrumentViewModel> Instruments { get; set; } = new ObservableCollection<InstrumentViewModel>();
}
public class InstrumentViewModel : ViewModelBase
{
    public InstrumentViewModel(string exchangeID, string instrumentID, string instrumentName)
    {
        ExchangeID = exchangeID;
        InstrumentID = instrumentID;
        InstrumentName = instrumentName;
    }

    private string _exchangeID = string.Empty;
    private string _instrumentID = string.Empty;
    private string _instrumentName = string.Empty;
    public string ExchangeID { get => _exchangeID; set => SetProperty(ref _exchangeID, value); }
    public string InstrumentID { get => _instrumentID; set => SetProperty(ref _instrumentID, value); }
    public string InstrumentName { get => _instrumentName; set => SetProperty(ref _instrumentName, value); }
}
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        parentContainer.DataContext = this;

        Exchanges = new();
        ExchangeViewModel exchange1 = new ExchangeViewModel();
        exchange1.ExchangeID = "SHSE";
        exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "601155", "新城控股"));
        exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "600036", "招商银行"));
        exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "600266", "城建发展"));
        exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "600837", "海通证券"));
        exchange1.Instruments.Add(new InstrumentViewModel("SHSE", "601668", "中国建筑"));
        ExchangeViewModel exchange2 = new ExchangeViewModel();
        exchange2.ExchangeID = "SZSE";
        exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "000002", "万科A"));
        exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "000001", "平安银行"));
        exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "000623", "吉林敖东"));
        exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "002739", "万达电影"));
        exchange2.Instruments.Add(new InstrumentViewModel("SZSE", "300642", "透景生命"));


        Exchanges.Add(exchange1);
        Exchanges.Add(exchange2);
    }

    public string BindData { get; set; } = "BindData";
    public ObservableCollection<ExchangeViewModel> Exchanges { get; set; }
}
相关推荐
Chris _data9 天前
WPF 学习第三天 — Modbus RTU 串口通信
hadoop·学习·wpf
布吉岛的石头10 天前
Java 程序员第 43 阶段05:微服务整合大模型,跨服务调用架构设计实战,Seata分布式事务实战
wpf
步步为营DotNet10 天前
基于.NET Aspire 实现云原生应用的高效监控与可观测性
云原生·.net·wpf
芒鸽10 天前
HarmonyOS 分布式开发实战:设备协同、数据共享与跨设备迁移
分布式·wpf·harmonyos
Volunteer Technology10 天前
Flink状态管理与容错(二)
大数据·flink·wpf
happyprince11 天前
07_verl-Trainer模块详解
人工智能·架构·wpf·强化学习
bugcome_com11 天前
WPF + Prism 技术指南与实战项目(二、模板搭建)
wpf
小满Autumn12 天前
log4net 日志框架 — 从配置到实战速查手册
笔记·c#·.net·wpf·上位机·log4net
政沅同学12 天前
基于 C# WPF + HALCON 的工业视觉算法工具框架(开源)
开发语言·c#·wpf
happyprince12 天前
03_verl-设计理念与核心原理
wpf