【问题标题】:INotifyPropertyChanged is implemented but not workingINotifyPropertyChanged 已实现但无法正常工作
【发布时间】:2019-01-03 21:34:12
【问题描述】:

我有一个使用 MVVM 模式并实现 INotifyPropertyChanged 的​​应用程序,但它不工作。基本上,当我从列表中选择 Wine 并单击“打开”时,应该加载另一个用户控件并填写所有详细信息。

我学习了复数视觉课程,并尝试对其进行调整并创建自己的东西。我已经阅读了复数视觉课程的源代码和堆栈溢出问题很多小时,只是看不到我缺少什么。在这里发疯.. :(

经过大量搜索,我知道我的数据绑定正在工作,因为我可以像这样强制更新目标:

txtWijnNaam.GetBindingExpression(TextBox.TextProperty).UpdateTarget();

我还尝试将 INotifyPropertyChanged 添加到我的 Wine 模型类以及视图模型中,但这不起作用。而且它也没有在复数课程的工作源代码中这样使用,所以应该没有必要。

我正在使用的视图模型:

class WineDetailViewModel : ViewModelBase
{
    private readonly string _baseUri = "https://localhost/api/wines";
    private IEventAggregator _eventAggregator;

    public WineDetailViewModel()
    {
        _eventAggregator = EventAggregatorSingleton.Instance;
        _eventAggregator.GetEvent<OpenWineDetailViewEvent>().Subscribe(OnOpenWineDetailView);
    }

    private void OnOpenWineDetailView(int wineId)
    {
        _wine = ApiHelper.GetApiResult<Wine>($"{ _baseUri}/{wineId}");
    }

    private Wine _wine;

    public Wine WineFull
    {
        get { return _wine; }
        set
        {
            _wine = value;
            OnPropertyChanged();
        }
    }
}

以及它继承自的基类,实现了 INotifyPropertyChanged 接口:

class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

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

我的 Xaml 文件的一部分,我尝试设置 updateSourceTrigger 就像我在此处的一些答案中看到的那样,但这也无济于事:

<UserControl x:Class="WineGUI.View.WineDetailView"
         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:WineGUI.View"
         xmlns:ViewModels="clr-namespace:WineGUI.ViewModel"
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<UserControl.DataContext>
    <ViewModels:WineDetailViewModel/>
</UserControl.DataContext>
<StackPanel>
    <Grid Margin="5">
        <TextBlock Text="Naam :" VerticalAlignment="Center"/>
        <TextBox Grid.Column="1" Name="txtWijnNaam" Margin="5" Text="{Binding WineFull.Name, Mode=TwoWay}"/>
        <TextBlock Grid.Row="1" Text="Jaar :" VerticalAlignment="Center"/>
        <TextBox Grid.Row="1" Grid.Column="1" Name="txtWijnYear" Margin="5" Text="{Binding WineFull.Year, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBlock Grid.Row="2" Text="Prijs :" VerticalAlignment="Center"/>

我确实注意到我的 WineFull 属性的 OnPropertyChanged() 方法从未被调用,但我不明白为什么。复数课程具有相同的设置(当然除了一些命名)并且效果很好..

任何帮助将不胜感激。如果我需要添加更多信息或代码,请告诉我。

【问题讨论】:

  • 在提出问题并尝试遵守所有规则和提示时,我是 SO 新手。因此,如果那些投反对票的人也给我一个理由,这样我就可以真正从中学习了。

标签: c# wpf mvvm inotifypropertychanged


【解决方案1】:

您正在设置支持字段的值而不是属性,因此永远不会调用 OnPropertyChanged 方法。

您可以在 OnOpenWineDetailView 方法中为 WineFull 属性调用 OnPropertyChanged:

private void OnOpenWineDetailView(int wineId)
{
    _wine = ApiHelper.GetApiResult<Wine>($"{ _baseUri}/{wineId}");
    OnPropertyChanged(nameof(WineFull));
}

或者你可以使用属性:

private void OnOpenWineDetailView(int wineId)
{
    WineFull= ApiHelper.GetApiResult<Wine>($"{ _baseUri}/{wineId}");
}

【讨论】:

  • 谢谢!!!标记为已接受的答案。我是个白痴.. :) 认为它是如此复杂,而它却如此简单。
猜你喜欢
  • 2017-02-09
  • 2010-12-30
  • 2017-03-15
  • 2011-12-18
  • 2017-10-05
  • 2015-02-05
  • 2011-06-16
  • 2013-05-21
  • 2015-03-26
相关资源
最近更新 更多