Назначать обновленные переменные данные текстовому блоку при каждом нажатии кнопки

#c# #wpf #xaml #desktop-application

#c# #wpf #xaml #рабочий стол-приложение

Вопрос:

Я пытаюсь создать небольшую программу, тогда как если вы нажмете кнопку увеличения, число добавит 1, и наоборот для кнопки уменьшения.

Мне удалось привязать значение _number к текстовому блоку (изначально заданному как 0), но когда я нажимаю кнопки, ни одна из них, похоже, не добавляет или не вычитает значение. Или если значение изменилось, но не обновилось в окне.

.xaml

 // MainWindow.xaml
<Window x:Class="Home_Test.MainWindow"
    ...
    Title="MainWindow" Height="450" Width="800">
<Grid Name="MainGrid">
    <Button ...
            Content="Add" 
            Click="increase"/>
    <Button ...
            Content="Subtract"
            Click="decrease"/>
    <TextBlock 
             Name="txtbox"
             HorizontalAlignment="Center" 
             Height="23" 
             TextWrapping="Wrap" 
             Text="{Binding Path=Number}" 
             Width="120"
             Margin="0,100,0,0" />
</Grid>
 

.xaml.cs

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

namespace Home_Test
{
    public partial class MainWindow : INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
        }

    private int _number = 0;
    public int Number
    {
        get { return _number; }
        set
        {
            if (_number != value)
            {
                _number = value;
            }
        }
    }

    public void increase(object sender, RoutedEventArgs e)
    {
        _number  = 1;
    }
    public void decrease(object sender, RoutedEventArgs e)
    {
        _number -= 1;
    }

    public event PropertyChangedEventHandler PropertyChanged;
}
 

}

В целом, я ожидал, что моя программа добавит 1 или вычтет 1 при нажатии кнопки. Я делаю что-то не так здесь?

Ответ №1:

У вас есть правильная идея, но у вас есть пара недостающих элементов:

1) Пользовательский интерфейс XAML отслеживает Number свойство на предмет изменений, чтобы оно могло обновляться, но ваши increase() decrease() методы and обновляют только резервную переменную. Вы должны установить Number свойство напрямую.

2) Ваш метод Number установки должен сообщать пользовательскому интерфейсу XAML об обновлении при его изменении. Это делается путем вызова OnPropertyChangedEvent в установщике свойств — см. https://docs.microsoft.com/en-us/dotnet/framework/winforms/how-to-implement-the-inotifypropertychanged-interface (В нем говорится о Windows forms, но механизм тот же)

Ответ №2:

Ваш XAML выглядит хорошо. Просто чтобы уточнить, вы не привязывались _number к текстовому блоку. _number является частной переменной и недоступна для пользовательского интерфейса. Вы привязали общедоступное свойство Number к текстовому блоку, как и следовало ожидать.

Как описывал Марс в своем посте, проблема возникает в вашей ViewModel. Установщику вашего Number свойства требуется вызов вашего метода PropertyChanged, который необходимо добавить; а ваши методы увеличения и уменьшения должны изменять Number свойство напрямую, а не его вспомогательную переменную. Когда вы просто изменяете резервную переменную, установщик вашего свойства никогда не вызывается, и поэтому пользовательский интерфейс никогда не обновляется.

Ниже показаны необходимые изменения кода:

 private int _number = 0;
public int Number
{
    get { return _number; }
    set
    {
        if (_number != value)
        {
            _number = value;
            //After the setter updates the backing variable, this Updates the UI.
            NotifyPropertyChanged("Number");
        }
    }
}

public void increase(object sender, RoutedEventArgs e)
{
    Number  = 1;
}
public void decrease(object sender, RoutedEventArgs e)
{
    Number -= 1;
}
 

Добавьте этот код, чтобы NotifyPropetyChanged функциональность работала.

 public event PropertyChangedEventHandler PropertyChanged;

public void NotifyPropertyChanged(string propertyName)
{
  if (PropertyChanged != null)
  {
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  }
}
 

Вы были там большую часть пути.

Ответ №3:

Метод set свойства number не запускает событие OnPropertyChanged . Подробности см. здесь https://docs.microsoft.com/en-us/dotnet/framework/wpf/data/how-to-implement-property-change-notification