我想在WPF表单上更新名称为“ CurrentMoney”的标签; 我写了从“ INotifyPropertyChanged”实现的Money类。
UPD:我已通过创建ViewModelBase类更改为MVVM模式。 仍然具有“ PropertyChaged”空值。如何解决它以及为什么会发生?
Money.cs
public class Money : ViewModelBase {
private double currentMoney;
public double CurrentMoney {
get => currentMoney;
set {
currentMoney = value;
OnPropertyChanged("CurrentMoney");
}
}
public Money() => currentMoney = 10000;
public int addMoney(double count) {
CurrentMoney += count;
return 1;
}
public int subMoney(double count) {
CurrentMoney -= count;
if (currentMoney < 0)
return 100;
return 1;
}
}
MainWindow.cs
public partial class MainWindow : Window {
public Money currentMoney;
public MainWindow ( ) {
InitializeComponent();
currentMoney = new Money();
CurrentMoney.DataContext = currentMoney;
}
private void Initialize() {
CurrentMoney.Content = "Current money: " + currentMoney.CurrentMoney;
CurrentPollution.Content = CurrentPollution.Content.ToString() + Pollution.CurrentPollution;
Facktories.Content = Facktories.Content.ToString() + FactoriesList.Quantity;
FactoriesPollution.Content = FactoriesPollution.Content.ToString() + FactoriesList.FullPolution;
}
private void MenuItem_Click(object sender, RoutedEventArgs e) {
var buy = new BuySMTH();
this.Visibility = Visibility.Collapsed;
buy.Show();
}
private void Window_ContentRendered(object sender, EventArgs e) {
Initialize();
}
private void Tmp_Click(object sender, RoutedEventArgs e) {
currentMoney.addMoney(1000);
}
MainWindow.xaml
<Window x:Class="Coursage.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:Coursage"
xmlns:model="clr-namespace:Coursage.Logic.Money"
mc:Ignorable="d"
ContentRendered="Window_ContentRendered"
Title="MainWindow" Height="450" Width="545.802">
<Window.Resources>
<model:Money x:Key="Money" ></model:Money>
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource Money}}">
<Menu Panel.ZIndex="-1" Height="25px" Width="Auto" Background="Yellow" Margin="0,0,0,398">
<MenuItem Header="Info" Background="Green"></MenuItem>
<MenuItem Header="Buy" Click="MenuItem_Click" Background="Red"></MenuItem>
<MenuItem Header="Info" Background="Blue"></MenuItem>
</Menu>
<Label Content="{Binding Path=CurrentMoney}" Name="CurrentMoney" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,23,0,0"/>
<Label Content="Population: " Name="Population" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,49,0,0"/>
<Label Content="Current pollution: " Name="CurrentPollution" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,80,0,0"/>
<Label Content="Number of factories: " Name="Facktories" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,235,0,0"/>
<Label Content="Pollution of factories: " Name="FactoriesPollution" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,261,0,0"/>
<Label Content="Number of cars: " Name="Cars" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="250,235,0,0"/>
<Label Content="Pollution of cars: " x:Name="CarsPollution" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="250,261,0,0"/>
<Label Content="Start Date: " x:Name="StartDate" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="267,25,0,0"/>
<Label Content="Day Count: " x:Name="DayCount" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="267,56,0,0"/>
<Label Content="Date: " x:Name="Date" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="267,80,0,0"/>
<Button Name="Tmp" Content="Button" HorizontalAlignment="Left" Margin="81,149,0,0" VerticalAlignment="Top" Width="75" Click="Tmp_Click"/>
</Grid>
答案 0 :(得分:1)
您应该在属性本身上实现接口。另外,在调用PropertyChanged事件时,应使用该事件的local(scoped)句柄以避免竞争情况。
public class Money : INotifyPropertyChanged {
double _currentMoney;
public event PropertyChangedEventHandler PropertyChanged;
public double CurrentMoney
{
get => _currentMoney;
set
{
_currentMoney = value;
OnPropertyChanged();
}
}
public Money() => CurrentMoney = 1000;
public int addMoney(double count) {
CurrentMoney += count;
return 1;
}
public int subMoney(double count) {
CurrentMoney -= count;
if (CurrentMoney < 0) { return 100; }
return 1;
}
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handle = PropertyChanged;
handle?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
编辑:要节省一些输入,您还可以创建一个ViewModelBase类来处理较小的细节。
public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handle = PropertyChanged;
handle?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public virtual void Dispose() => PropertyChanged = null;
}
然后,在实现viewModel类时,它仅继承自base(但仍会通知属性更改)。
public class MyClass : ViewModelBase
{
string _myField;
public string MyProperty
{
get => _myField;
set
{
_myField = value;
OnPropertyChanged();
}
}
}
注意:实际的错误来自[CallerMemberName]属性,并从另一个方法中调用该方法。您可以传入属性的名称作为参数,也可以将方法与属性本身一起使用,而不必指定属性名称。
答案 1 :(得分:0)
您需要传递修改后的道具名称
NotifyPropertyChanged("CurrentMoney");
答案 2 :(得分:0)
NotifyPropertyChanged采用propertyName作为参数。默认值为空。
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
如果要在ui上查看对“ propertyName”的更改,可以使用NotifyPropertyChanged(“ propertyName”)。
对于您的示例,propertyName为“ CurrentMoney”