当另一个类中的属性发生变化时,如何在我的窗口中绑定该属性的变化?

后端开发 2026-07-12

我想让属性 UserBalance 在窗口中改变,但这个变化发生在另一个类中。

这是我的 bankaccount.cs,其中有余额,并且通过deposit等方法来改变:

public class BankAccount : INotifyPropertyChanged
{
    private decimal _balance;
    public decimal Balance
    {
        get { return _balance; }
        private set
        {
            if (_balance != value)
            {
                _balance = value;
                NotifyPropertyChanged();
            }
        }

    }

    public event PropertyChangedEventHandler? PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

这是 dashboard.xaml.cs,我希望余额的变化能够在窗口的文本块中显示:

public partial class Dashboard : Window, INotifyPropertyChanged
{
     private static readonly CultureInfo EuroInfo = new("de-DE");
     private User? _currentUser;
     private UserRepository? _allUsers;
     private decimal _userBalance;

     public decimal UserBalance
     {
         get => _userBalance;
         set
         {
             if (_userBalance != value)
             {
                 _userBalance = value;
                 NotifyPropertyChanged();
             }
         }
     }

     public event PropertyChangedEventHandler? PropertyChanged;
     private void NotifyPropertyChanged(string propertyName = null)
     {
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     }

     public Dashboard(User currentUser, UserRepository allUsers)
     {
         InitializeComponent();
         this.DataContext = this;

         try
         {
             this.Title = currentUser.FullName;
             _currentUser = currentUser;
             _allUsers = allUsers;

             UserBalance = _currentUser?.BankAccount?.Balance ?? 0m;
         }
         catch (NullReferenceException e)
         {
             MessageBox.Show(e.StackTrace);
         }
    }
}

在问题尚未公开时,有人告诉我窗口不应该拥有INotifyPropertyChanged,所以我就在我的adshboard.xaml.cs中添加了一个方法,并把它与BankAccount的 PropertyChanged事件绑定起来 这就是我的dashboard.xaml.cs的样子:

public partial class Dashboard : Window
{
    //i save the user and the list to pass their values to other windows as well
    private User? _currentUser;
    private UserRepository? _allUsers;

    //i create the balance prop so we can see the changes in the window
    private decimal _userBalance;

    public decimal UserBalance
    {
        get => _userBalance;
        set
        {
            _userBalance = value;
        }
    }

    public Dashboard(User currentUser, UserRepository allUsers)
    {
        InitializeComponent();
        this.DataContext = currentUser;

        try
        {
            this.Title = currentUser.FullName;
            _currentUser = currentUser;
            _allUsers = allUsers;

            UserBalance = _currentUser?.BankAccount?.Balance ?? 0m;
            if (currentUser.BankAccount != null)
                _currentUser.BankAccount.PropertyChanged += BankAccount_PropertyChanged;

        }
        catch (NullReferenceException e)
        {
            MessageBox.Show(e.StackTrace);
        }
        catch (Exception e)
        {
            MessageBox.Show(e.GetType() + e.StackTrace);
        }
    }

    private void BankAccount_PropertyChanged(object? sender, PropertyChangedEventArgs e)
    {
        if (e == null || e.PropertyName == null || e.PropertyName == nameof(BankAccount.Balance))
            Dispatcher.Invoke(() => UserBalance = _currentUser?.BankAccount?.Balance ?? 0m);
    }

解决方案

你在混用两个概念:一方面你想使用数据绑定,另一方面你在代码背后(即 *.xaml.cs 文件)写了大量逻辑来处理数值变化。数据绑定的要点在于让 *.xaml.cs 文件保持不变(也就是说那里不再添加代码),并在 *.xaml 文件中使用数据绑定。

对于这个示例,我对 BankAccount.cs 做了略微修改。

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace MultiWindowBind;

public class BankAccount : INotifyPropertyChanged
{
    private decimal _balance;
    public decimal Balance
    {
        get => _balance;
        set // <-----------changed to be public for this example
        {
            if (_balance != value)
            {
                _balance = value;
                NotifyPropertyChanged();
            }
        }
    }

    public event PropertyChangedEventHandler? PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

我创建了一个 Dashboard.xaml,里面带有一个 TextBox 用来编辑 Balance 属性:

<Window x:Class="MultiWindowBind.Dashboard"
        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:MultiWindowBind" d:DataContext="{d:DesignInstance Type=local:BankAccount}"
        mc:Ignorable="d"
        Title="Dashboard" Height="200" Width="300">
    <TextBox Text="{Binding Balance, UpdateSourceTrigger=PropertyChanged}"/>
</Window>

如前所述,我没有在 Dashboard.xaml.cs 上添加任何逻辑:

using System.Windows;

namespace MultiWindowBind
{
    /// <summary>
    /// Interaction logic for Dashboard.xaml
    /// </summary>
    public partial class Dashboard : Window
    {
        public Dashboard()
        {
            InitializeComponent();
        }
    }
}

我添加了第二个窗口 YetAnotherDashboard.xaml,它通过一个 TextBlock 和一个 Label 显示 Balance 属性的值:

<Window x:Class="MultiWindowBind.YetAnotherDashboard"
        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:MultiWindowBind" d:DataContext="{d:DesignInstance Type=local:BankAccount}"
        mc:Ignorable="d"
        Title="YetAnotherDashboard" Height="200" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Content="Balance"/>
        <TextBlock Text="{Binding Balance}"
                   Grid.Column="1"/>
    </Grid>
</Window>

同样,没有在 YetAnotherDashboard.xaml.cs 上添加任何逻辑:

using System.Windows;

namespace MultiWindowBind
{
    /// <summary>
    /// Interaction logic for YetAnotherDashboard.xaml
    /// </summary>
    public partial class YetAnotherDashboard : Window
    {
        public YetAnotherDashboard()
        {
            InitializeComponent();
        }
    }
}

要把它们绑定在一起,你需要创建一个单一的 BankAccount 对象,使其同时绑定到两个窗口的 DataContext,从而在它们之间共享。 在应用初始化时,我是这样做的:

var account = new BankAccount();

var dashboard = new Dashboard
{
    DataContext = account
};
dashboard.Show();

var yetAnotherDashboard = new YetAnotherDashboard
{
    DataContext = account
};
yetAnotherDashboard.Show();

这就是你所需要的全部。运行应用时,你会看到在 YetAnotherDashboard 显示的值 123645 与在 Dashboard 输入的值绑定为同一个。

三窗口应用

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章