如何实现 INotifyPropertyChange (WPF, MVVM)

How to implement INotifyPropertyChange (WPF, MVVM)

当我在我的 ViewModel 中设置默认值时,它有效,但是当我更改任何内容时,视图保持不变....所以我认为这与 INotifyPropertyChanged 有关。 我已经花了大约 10 个小时 "googleing",但我找不到问题所在。 所以这是我的代码,我希望你能告诉我哪里出了问题:)

我的看法:

<UserControl x:Class="Diplomarbeit.Views.TasteView" 
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Diplomarbeit"
         mc:Ignorable="d"
         >
<Grid>
    <Ellipse x:Name="Taste" Fill="{Binding FillColor, Mode=TwoWay}" Stroke="{Binding BorderColor, Mode=TwoWay}" StrokeThickness="10" Height="{Binding ActualWidth, RelativeSource={RelativeSource Self}}" Margin="2,0,2,0"/>
    <Viewbox>
        <Label x:Name="TasteText" Content="{Binding Text, Mode=TwoWay}" Foreground="{Binding TextColor, Mode=TwoWay}" FontWeight="ExtraBold" VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </Viewbox>
</Grid>

视图的代码隐藏:

    public partial class TasteView : UserControl
{
    public TasteView()
    {
        InitializeComponent();
        // DataContext der View auf ViewModel binden
        this.DataContext = new TasteViewModel();
    } 
}

我的视图模型:

public class TasteViewModel : INotifyPropertyChanged
{
    #region PropertyChanged-Event + Methode
    public event PropertyChangedEventHandler PropertyChanged; // Event wird deklariert

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); // Event wird gefeuert
        }
    }
    #endregion

    #region Felder
    //ID für Eindeutigkeit
    private int _iD;
    //Füllfarbe der Ellipse
    private SolidColorBrush _fillColor;
    //Randfarbe der Ellipse
    private SolidColorBrush _borderColor;
    //Text der im Label steht; ACHTUNG: Vor und nach der Zahl 2 Leerzeichen!
    private string _text;
    //Farbe des Texts im Label
    private SolidColorBrush _textColor;
    #endregion

    #region Eigenschaften

    //ID für Eindeutigkeit
    public int ID
    {
        get { return _iD; }
        set
        {
            if (value != _iD)
            {
                _iD = value;
                OnPropertyChanged("ID");
            }
        }
    }

    //Füllfarbe der Ellipse
    public SolidColorBrush FillColor
    {
        get { return _fillColor; }
        set
        {
            if (value != _fillColor)
            {
                _fillColor = value;
                OnPropertyChanged("FillColor");
            }
        }
    }

    //Randfarbe der Ellipse
    public SolidColorBrush BorderColor
    {
        get { return _borderColor; }
        set
        {
            if (value != _borderColor)
            {
                _borderColor = value;
                OnPropertyChanged("BorderColor");
            }
        }
    }

    //Text der im Label steht
    public string Text 
    {
        get { return _text; }
        set
        {
            if (value != _text)
            {
                _text = value;
                OnPropertyChanged("Text");
            }
        }
    }

    //Farbe des Texts im Label
    public SolidColorBrush TextColor 
    {
        get { return _textColor; }
        set
        {
            if (value != _textColor)
            {
                _textColor = value;
                OnPropertyChanged("TextColor");
            }
        }
    }
    #endregion     

    #region Konstruktoren

    //Farbige Taste mit Border, Text und ID ==> Vollständige Taste 
    public TasteViewModel(int iD, SolidColorBrush fillColor, SolidColorBrush borderColor, string text, SolidColorBrush textColor)
    {
        iD = ID;
        fillColor = FillColor;
        borderColor = BorderColor;
        text = Text;
        textColor = TextColor;
    }

    //Farbige Taste mit Border und ID, jedoch ohne Text
    public TasteViewModel(int iD, SolidColorBrush fillColor, SolidColorBrush borderColor)
    {
        iD = ID;
        fillColor = FillColor;
        borderColor = BorderColor;
    }

    //Leere Taste, allerdings mit ID
    public TasteViewModel(int iD)
    {
        iD = ID;
    }

    //Leere Taste
    public TasteViewModel()
    {

    }
    #endregion

你的构造函数是错误的:

//Farbige Taste mit Border, Text und ID ==> Vollständige Taste 
    public TasteViewModel(int iD, SolidColorBrush fillColor, SolidColorBrush borderColor, string text, SolidColorBrush textColor)
    {
        ID = iD;
        FillColor = fillColor ;
        BorderColor = borderColor;
        Text = text;
        TextColor = textColor;
    }

另外两个也一样

编辑: 双向绑定是默认行为,无需在 xaml.

中明确说明

如果您使用的是 c# 6 或更新版本,您应该对 OnPropertyChanged()

使用 nameof() 运算符

仅供参考,我倾向于将此模式与一些辅助属性一起使用。

public class ViewModel: INotifyPropertyChanged
{
    private string _text;
    public string Text
    {
        get { return _text; }
        set
        {
            if (value == _text) return;
            _text= value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
 }

应该可以。

...或者因为它被否决了:也许不会。尽管如此。尝试使用助手。它可以保护您免受非强类型输入错误的影响。

您在 TasteView.Xaml.cs 中设置了无效的构造函数。应该是

public TasteView()
{
    InitializeComponent();
    // DataContext der View auf ViewModel binden
    this.DataContext = new TasteViewModel(1,Brushes.Red,Brushes.Green,"Taste",Brushes.Blue);
} 

那个构造函数应该如下所示。

public TasteViewModel(int iD, SolidColorBrush fillColor, SolidColorBrush borderColor, string text, SolidColorBrush textColor)
    {
        ID = iD;
        FillColor = fillColor;
        BorderColor = borderColor;
        Text = text;
        TextColor = textColor;
    }`

希望这对你有用。