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; }
}
相关推荐
软泡芙18 小时前
【WPF 】MVVM 设计模式在 WPF 中的实战应用
设计模式·wpf
张小俊_19 小时前
WPF 跨线程 UI 更新与硬编码赋值引发的 Bug 排查
c#·bug·wpf
七夜zippoe2 天前
DolphinDB在工业物联网中的优势
物联网·wpf·工业物联网·优势·dolphindb
heimeiyingwang2 天前
【架构实战】观察者模式在分布式系统中的应用
观察者模式·架构·wpf
bugcome_com2 天前
WPF + Microsoft.ToolKit.Mvvm 技术指南与实战项目
microsoft·wpf
武藤一雄3 天前
WPF中逻辑树(Logical Tree)与可视化树(Visual Tree)到底是什么
microsoft·c#·.net·wpf·.netcore
炸炸鱼.3 天前
ELK 企业级日志分析系统完整部署手册
elk·wpf
Mr_pyx4 天前
微服务可观测性实战:分布式链路追踪从入门到精通
wpf
c#上位机5 天前
wpf附加事件
wpf
玖笙&5 天前
✨WPF编程进阶【9.1】:WPF资源完全指南(附源码)
c++·c#·wpf·visual studio