Существуют некоторые фреймворки, предоставляющие класс, уже реализующий необходимые интерфейсы, если вы хотите сделать это самостоятельно, вот такая возможность:
Сначала у вас есть ViewModelBase, и все ваши ViewModels должны наследовать его
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
, затем в вашей модели представления вы объявите свою собственность следующим образом:
private String _mBalance;
public String Balance
{
get { return _mBalance; }
set => SetAndRaisePropertyChanged(ref _mBalance, value);
}
[РЕДАКТИРОВАТЬ]: я хочу сохранить историю ответа, поэтому проверьте мое редактирование ниже на полном примере:
Обычно я делю на несколько файлов, но я хотел остаться простым, поэтому вам нужно 2 файла (я пытаюсь применить шаблон MVVM, поэтому я добавляю каталоги): - Views \ MainWindow.xaml - ViewModels\ MainWindowViewModel.cs
Views \ MainWindow.xaml:
<Window x:Class="StackOverflow_DBG.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:StackOverflow_DBG"
xmlns:viewmodels="clr-namespace:StackOverflow_DBG.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="100" Width="400">
<Window.DataContext>
<viewmodels:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="1" Grid.Column="0" Content="{Binding LabelTxt}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding ValueTxt}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Change Label" Command="{Binding ChangeLabel}"/>
</Grid>
</Window>
ViewModels \ MainWindowViewModel.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace StackOverflow_DBG.ViewModels
{
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual bool SetAndRaisePropertyChanged<T>(ref T storage, T value, [CallerMemberName] string propertyName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value))
return false;
storage = value;
this.RaisePropertyChanged(propertyName);
return true;
}
}
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null)
{
return true;
}
else
{
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
class MainWindowViewModel : ViewModelBase
{
private String m_LabelTxt = "Foo";
public String LabelTxt
{
get { return m_LabelTxt; }
set => SetAndRaisePropertyChanged(ref m_LabelTxt, value);
}
private String m_ValueTxt;
public String ValueTxt
{
get { return m_ValueTxt; }
set => SetAndRaisePropertyChanged(ref m_ValueTxt, value);
}
private RelayCommand m_ChangeLabel;
public RelayCommand ChangeLabel
{
get { return m_ChangeLabel; }
set { m_ChangeLabel = value; }
}
public MainWindowViewModel()
{
ChangeLabel = new RelayCommand(() => {
if (LabelTxt == "Foo")
{
LabelTxt = "Bar ";
}
else
{
LabelTxt = "Foo ";
}
});
}
}
}
Таким образом, вы также видите, как связать кнопку дляпример.Нажмите кнопку, чтобы увидеть, что обновление сделано хорошо.Если вы используете те же каталоги, что и я, не забудьте отредактировать app.xaml, чтобы использовать StartupUri="Views/MainWindow.xaml">
вместо
StartupUri="MainWindow.xaml">