我尝试做一些简单的事情,但似乎我想念一些事情。当我点击按钮时,我尝试更改标签的内容。我使用MVVM模式。这是我的代码:
查看:
<Button x:Name="buttonNext"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Grid.Column="1"
Grid.Row="2"
Width="85"
Height="35"
Style="{StaticResource AccentedSquareButtonStyle}"
Command="{Binding Path=Next}">
<TextBlock Text="Next"
TextWrapping="Wrap"
TextAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Button>
<Label Name="Path"
Grid.ColumnSpan="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding path}"
FontWeight="Bold"
Foreground="DeepSkyBlue"
/>
ViewModel:
public ICommand Next { get; set; }
private string _path;
public string path
{
get
{
return _path;
}
set
{
_path = value;
RaisePropertyChanged("path");
}
}
public event PropertyChangedEventHandler PropertyChanged = null;
protected virtual void RaisePropertyChanged(string propName)
{
if (PropertyChanged != null)
{
Task.Run(() => PropertyChanged(this, new PropertyChangedEventArgs(propName)));
}
}
public page4ViewModel(NavigationViewModel navigationViewModel)
{
_path = "etape1";
Next = new BaseCommand(GoNext);
}
private void GoNext(object obj)
{
switch (_path)
{
case "etape1":
_path = "etape2";
break;
case : "etape2"
_path = "etape3";
break;
case "etape3":
_path = "etape4";
break;
default:
_path = " ";
break;
}
}
首先,标签是“etape1”,就像在构造函数中一样,但是当我点击下一个按钮时,值不会改变。 ps:改变的功能是因为我设置了一个断点来看。谢谢你的帮助
答案 0 :(得分:3)
您必须使用该属性,而不是支持字段。
private void GoNext(object obj)
{
switch (_path)
{
case "etape1":
path = "etape2"; // without underscore
break;
case : "etape2"
path = "etape3";
break;
case "etape3":
path = "etape4";
break;
default:
path = " ";
break;
}
这将引发变更通知
修改强>
使用ViewModelBase
进行ViewModel
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
您可以在其中定义
protected virtual void RaisePropertyChanged(string propertyName)
{
this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
<强>替代强>
根据this评论,我们可以介绍CallerMemberName
protected virtual void RaisePropertyChanged<T>([CallerMemberName] string propertyName = null)
另一个有用的变体基于选择器,当你需要从不同的 setter
中为依赖属性引发它时 protected virtual void RaisePropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
if (selectorExpression == null)
throw new ArgumentNullException("selectorExpression");
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The body must be a member expression");
RaisePropertyChanged(body.Member.Name);
}
答案 1 :(得分:2)
您需要在ui线程上引发属性更改事件。
替换
if (PropertyChanged != null)
{
Task.Run(() => PropertyChanged(this, new PropertyChangedEventArgs(propName)));
}
与
if (PropertyChanged != null)
{
Application.Current.Dispatcher.Invoke(() => PropertyChanged(this, new PropertyChangedEventArgs(propName)));
}
同时设置path
而不是_path
<强>更新强>
正如评论中所指出的,在这种情况下,Dispatcher.Invoke不是必需的,因为它已经在UI线程上。
致电
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
答案 2 :(得分:0)
您正在更改以下值:
private void GoNext(object obj)
{
switch (_path)
{
case "etape1":
_path = "etape2";
break;
case : "etape2"
_path = "etape3";
break;
case "etape3":
_path = "etape4";
break;
default:
_path = " ";
break;
}
但是当你设置_path
时,path
中的setter从未被调用过:
public string path
{
set ///This is never called
{
_path = value;
RaisePropertyChanged("path");
}
}
更改为:
switch (path)
{
case "etape1":
path = "etape2";
break;
case : "etape2"
path = "etape3";
break;
case "etape3":
path = "etape4";
break;
default:
path = " ";
break;
}