如何实现 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;
}`
希望这对你有用。
当我在我的 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;
}`
希望这对你有用。