WPF - MVVM - 更改 VM 实例的属性时视图不会更新
WPF - MVVM - View doesn't update when changing properties of a VM instance
我对 MVVM 和 WPF 还很陌生,所以请对我所说的一切持保留态度。我的问题非常复杂,过去一天我一直在努力寻找解决方案。无果...
上下文
我正在尝试自己制作一个POS系统。一切都按计划进行。在此之前:当扫描的条形码太短时,我会打开一个小视图,询问文章的尺寸和颜色代码。这是通过 ICommand 完成的。
我可以写一篇文章并将其添加到我的 ObservableCollection 中。我使用从 ViewModel 创建的实例访问这个可观察集合。
但是现在奇怪的事情发生了,我也更新了一个“total”texblock 和一个“amount”文本块。这些更改完成后,我可以看到正在填充的属性并且正在触发我的 OnPropertyChanged 但在视图上看不到任何内容。奇怪的是我的 ObservableCollection 正在改变但我的文本框没有。
我非常确信我的 ICommand 没有任何问题,因为我可以创建实际的文章并将其添加到我的购物车。我已经尝试调试了一段时间,我可以看到它正在使用正确的值检查我的属性的 setter。奇怪的是,如果我添加这样的文章,文本块将是错误的,但是当我以另一种方式添加新文章时(通过原始 VM - 而不是新的 window),它需要正确的总数和数量.这就像我的视图不想更新,我不知道如何强制它更新。
我一直在努力寻找一种方法让一切正常,希望有人能告诉我我做错了什么,因为我几乎一无所知! :D
下面的代码中可能存在输入错误或类似问题,但我敢肯定您可以忽略最基本的内容。我正在实施一切,变化正在发生,只是没有出现。
代码
示例 属性 更改后拒绝显示:
(这些属性在我的主 VM 中)
private static string _totalstr { get; set; }
public string TotalStr
{
get { return _totalstr; }
set
{
_totalstr = value;
OnPropertyChanged(nameof(TotalStr));
}
}
我添加文章后显示更改的购物车
private static ObservableCollection<Art> _cart;
public ObservableCollection<Art> Cart
{
get
{
return _cart;
}
set
{
_cart = value;
OnPropertyChanged(nameof(Cart));
}
}
询问尺寸 - VM
这是一个小版本,因为发生的事情不止于此,但这就是它的要点。还有一些部分是我的母语,所以我尽力翻译了。
public ICommand SizeColorCommand { get; set; }
public SizeColorViewModel()
{
this.SizeColorCommand = new SizeColorCommand(this);
}
public void function(object parameter)
{
MainViewModel.Instance.Cart.Add(artikel);
MainViewModel.Instance.Total += (double)article.EVkp;
MainViewModel.Amount++;
MainViewModel.Instance.TotaalStr = String.Format("{0:c}", MainViewModel.Instance.Total);
}
大小颜色命令
class SizeColorCommand: ICommand
{
public SizeColorViewModel VM { get; set; }
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public SizeColorCommand(SizeColorViewModel vm)
{
VM = vm;
}
public bool CanExecute(object parameter)
{
string query = parameter as string;
if (string.IsNullOrWhiteSpace(query))
return false;
return true;
}
public void Execute(object parameter)
{
VM.function(parameter);
}
}
询问尺码 - XAML
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding SizeColorCommand}" CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
</TextBox.InputBindings>
</TextBox>
MainVM - XAML
<TextBlock Text="{Binding TotalStr, Mode=TwoWay}"/>
截图#
picture of the POS, it's in Dutch so sorry in advance, Stuks/Aantal = AMOUNT
非常感谢您远道而来帮助我。我希望我能学习并解决这个问题。今天下午我读了很多书,单例可能不是最好的选择,但我似乎想不出更好的方法。
确保 MainViewModel.Instance 是 MainWindow 的 DataContext。最简单的方法是指定属性:DataContext="{x:Static local:MainViewModel.Instance}"
您需要将 TextBox.Text
绑定指定为 {Binding PropertyName, Mode=TwoWay}
。
编辑:
如果 Cart
通过 ListBox 或 ComboBox 在 UI 中公开,您还可以指定 TextBox 应使用其选择的值作为 Binding 的参考点,如下所示: Text="{Binding ElementName=nameOfTextBoxInXAML, Path=SelectedItem.PropertyOnSelectedValue"
使用此语法可确保您的文本框始终使用所选项目的值。
我对 MVVM 和 WPF 还很陌生,所以请对我所说的一切持保留态度。我的问题非常复杂,过去一天我一直在努力寻找解决方案。无果...
上下文
我正在尝试自己制作一个POS系统。一切都按计划进行。在此之前:当扫描的条形码太短时,我会打开一个小视图,询问文章的尺寸和颜色代码。这是通过 ICommand 完成的。
我可以写一篇文章并将其添加到我的 ObservableCollection 中。我使用从 ViewModel 创建的实例访问这个可观察集合。
但是现在奇怪的事情发生了,我也更新了一个“total”texblock 和一个“amount”文本块。这些更改完成后,我可以看到正在填充的属性并且正在触发我的 OnPropertyChanged 但在视图上看不到任何内容。奇怪的是我的 ObservableCollection 正在改变但我的文本框没有。 我非常确信我的 ICommand 没有任何问题,因为我可以创建实际的文章并将其添加到我的购物车。我已经尝试调试了一段时间,我可以看到它正在使用正确的值检查我的属性的 setter。奇怪的是,如果我添加这样的文章,文本块将是错误的,但是当我以另一种方式添加新文章时(通过原始 VM - 而不是新的 window),它需要正确的总数和数量.这就像我的视图不想更新,我不知道如何强制它更新。
我一直在努力寻找一种方法让一切正常,希望有人能告诉我我做错了什么,因为我几乎一无所知! :D
下面的代码中可能存在输入错误或类似问题,但我敢肯定您可以忽略最基本的内容。我正在实施一切,变化正在发生,只是没有出现。
代码
示例 属性 更改后拒绝显示:
(这些属性在我的主 VM 中)
private static string _totalstr { get; set; }
public string TotalStr
{
get { return _totalstr; }
set
{
_totalstr = value;
OnPropertyChanged(nameof(TotalStr));
}
}
我添加文章后显示更改的购物车
private static ObservableCollection<Art> _cart;
public ObservableCollection<Art> Cart
{
get
{
return _cart;
}
set
{
_cart = value;
OnPropertyChanged(nameof(Cart));
}
}
询问尺寸 - VM
这是一个小版本,因为发生的事情不止于此,但这就是它的要点。还有一些部分是我的母语,所以我尽力翻译了。
public ICommand SizeColorCommand { get; set; }
public SizeColorViewModel()
{
this.SizeColorCommand = new SizeColorCommand(this);
}
public void function(object parameter)
{
MainViewModel.Instance.Cart.Add(artikel);
MainViewModel.Instance.Total += (double)article.EVkp;
MainViewModel.Amount++;
MainViewModel.Instance.TotaalStr = String.Format("{0:c}", MainViewModel.Instance.Total);
}
大小颜色命令
class SizeColorCommand: ICommand
{
public SizeColorViewModel VM { get; set; }
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public SizeColorCommand(SizeColorViewModel vm)
{
VM = vm;
}
public bool CanExecute(object parameter)
{
string query = parameter as string;
if (string.IsNullOrWhiteSpace(query))
return false;
return true;
}
public void Execute(object parameter)
{
VM.function(parameter);
}
}
询问尺码 - XAML
<TextBox>
<TextBox.InputBindings>
<KeyBinding Key="Enter" Command="{Binding SizeColorCommand}" CommandParameter="{Binding Path=Text, RelativeSource={RelativeSource AncestorType={x:Type TextBox}}}" />
</TextBox.InputBindings>
</TextBox>
MainVM - XAML
<TextBlock Text="{Binding TotalStr, Mode=TwoWay}"/>
截图#
picture of the POS, it's in Dutch so sorry in advance, Stuks/Aantal = AMOUNT
非常感谢您远道而来帮助我。我希望我能学习并解决这个问题。今天下午我读了很多书,单例可能不是最好的选择,但我似乎想不出更好的方法。
确保 MainViewModel.Instance 是 MainWindow 的 DataContext。最简单的方法是指定属性:
DataContext="{x:Static local:MainViewModel.Instance}"
您需要将
TextBox.Text
绑定指定为{Binding PropertyName, Mode=TwoWay}
。
编辑:
如果 Cart
通过 ListBox 或 ComboBox 在 UI 中公开,您还可以指定 TextBox 应使用其选择的值作为 Binding 的参考点,如下所示: Text="{Binding ElementName=nameOfTextBoxInXAML, Path=SelectedItem.PropertyOnSelectedValue"
使用此语法可确保您的文本框始终使用所选项目的值。