INotifyPropertyChanged и его нулевое событие - PullRequest
0 голосов
/ 22 апреля 2019

Я хочу обновить свой ярлык на бланке WPF с именем «CurrentMoney»; Я написал класс Money, который был реализован из "INotifyPropertyChanged".

UPD: я изменен на шаблон MVVM с созданием класса ViewModelBase. Все еще имеют "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>

Ответы [ 3 ]

1 голос
/ 23 апреля 2019

Вы должны реализовать интерфейс на самом свойстве. Кроме того, при вызове события PropertyChanged вы должны использовать локальный (ограниченный) дескриптор события, чтобы избежать условий гонки.

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 просто наследуйте от базы (но все равно уведомляйте об изменениях свойств).

public class MyClass : ViewModelBase
{
    string _myField;
    public string MyProperty
    {
        get => _myField;
        set
        {
            _myField = value;
            OnPropertyChanged();
        } 
    }
}

ПРИМЕЧАНИЕ. Фактическая ошибка возникает из атрибута [CallerMemberName] и вызова метода из другого метода. Вы можете передать имя свойства в качестве параметра или использовать метод from вместе с самим свойством без указания имени свойства.

0 голосов
/ 23 апреля 2019

NotifyPropertyChanged принимает свойство propertyName в качестве параметра.Значение по умолчанию - null.

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

Вы можете использовать NotifyPropertyChanged ("propertyName"), если хотите увидеть изменения в "propertyName" на пользовательском интерфейсе.

Для вашего примера propertyName is "CurrentMoney "

0 голосов
/ 23 апреля 2019

Вам необходимо передать измененное имя реквизита

NotifyPropertyChanged("CurrentMoney");

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...