C# 实现INotifyPropertyChanged的属性中的更改未反映在UI中

C# 实现INotifyPropertyChanged的属性中的更改未反映在UI中,c#,xamarin,mvvm,data-binding,viewmodel,C#,Xamarin,Mvvm,Data Binding,Viewmodel,我正在尝试实现MVVM模式,但不幸的是,它花费的时间比预期的要长 我有一个由ContactsSVM的ObservableCollection填充的ListView,添加或删除Contacts效果很好,当试图通过选择它来更改此集合中的一个项目时,问题就出现了 我在其中设置绑定的Xaml: <ListView ItemsSource="{Binding ContactsToDisplay}" SelectedItem="{Binding SelectedC

我正在尝试实现MVVM模式,但不幸的是,它花费的时间比预期的要长

我有一个由ContactsSVM的ObservableCollection填充的ListView,添加或删除Contacts效果很好,当试图通过选择它来更改此集合中的一个项目时,问题就出现了

我在其中设置绑定的Xaml:

<ListView ItemsSource="{Binding ContactsToDisplay}" 
                  SelectedItem="{Binding SelectedContact, Mode=TwoWay}"
                  SeparatorColor="Black" 
                  ItemSelected="OnItemSelected">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextCell Text="{Binding FirstName}" 
                              Detail="{Binding Id}">
                        <TextCell.ContextActions>
                            <MenuItem 
                                Text="Delete" 
                                IsDestructive="true" 
                                Clicked="Delete_OnClicked"
                                CommandParameter="{Binding .}" />
                        </TextCell.ContextActions>
                    </TextCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView> 
BaseViewModel:

public class BaseViewModel
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

        protected void SetValue<T>(ref T backingField, T value, [CallerMemberName]string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(backingField, value))
                return;
            backingField = value;
            OnPropertyChanged(propertyName);
        }
    }
公共类BaseViewModel
{
公共事件属性更改事件处理程序属性更改;
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
受保护的void SetValue(ref T backingField,T value,[CallerMemberName]字符串propertyName=null)
{
if(EqualityComparer.Default.Equals(backingField,value))
返回;
backingField=值;
OnPropertyChanged(propertyName);
}
}
如您所见,我正在尝试更新每个选定联系人的FirstName=“Test”,更改后的联系人将被更新,但不幸的是,这些联系人没有反映在UI中,希望您能帮助我找到我做错的地方


提前谢谢

我猜
NotifyPropertyChangedInvocator
属性没有正确地通知属性更改。但我对此不确定。因为您的BaseViewModel没有实现INotifyPropertyChanged接口

下面的代码对我来说很好。这就是我在整个项目中使用它的方式

我已经在我的
BaseModel
中直接派生了
INotifyPropertyChanged
接口,并实现了属性更改

public class BaseModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class ContactVm : BaseModel
{
    private string _firstName;

    public int Id { get; set; }

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            this._firstName = value;
            NotifyPropertyChanged();
        }
    }
}
这是我回电话的内容

public void SelectContact(ContactVm contact)
{
    if (contact == null)
        return;
    contact.FirstName = "Test";
}
唯一的区别是我也在ViewModel中实现了ObservableCollection的属性更改

public ObservableCollection<ContactVm> ContactsToDisplay 
{
    get { return _contactsToDisplay; }
    set
    {
        this._contactsToDisplay = value;
        NotifyPropertyChanged();
    }
}
public ObservableCollection contacts可显示
{
获取{return\u contactsToDisplay;}
设置
{
这。_contactsstodisplay=值;
NotifyPropertyChanged();
}
}
请注意,在我的案例中,我没有使用您的SelectedContact绑定。可能正如你所说,约束将是一个问题


我希望它能帮助你

因为您使用了MVVM,所以当您在listview中选择item时,您可以在ViewModel中直接处理逻辑(不再需要定义ItemSelected事件)


不要忘了对您的模型和viewmodel实现INotifyPropertyChanged。

您的BaseViewModel没有实现INotifyPropertyChanged接口。

我刚刚测试了它,不幸的是它不起作用,可能绑定有问题吗?它对我来说很好。我所能看到的只是BaseViewModel没有实现INotifyPropertyChanged接口。除此之外,唯一的区别是我还为视图模型更改了属性通知。我还没有绑定所选联系人。可能是绑定是不需要的,因此它实际上可能会还原发生的更改。我修改过的答案对我来说很好。如果它仍然不起作用,你最好分享你的样本,这样我就可以在我这边测试它。我至少可以知道为什么我的问题被否决了吗?是的。这也是我在回答中提到的。希望你工作顺利。快乐编码…)@维克多,如果我的回答解决了你的问题,欢迎你接受。不是真的,但不管怎样。是现在吗?请检查一下是的,是的。谢谢
public class BaseModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void NotifyPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
    {
        if (this.PropertyChanged != null)
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

public class ContactVm : BaseModel
{
    private string _firstName;

    public int Id { get; set; }

    public string FirstName
    {
        get { return _firstName; }
        set
        {
            this._firstName = value;
            NotifyPropertyChanged();
        }
    }
}
public void SelectContact(ContactVm contact)
{
    if (contact == null)
        return;
    contact.FirstName = "Test";
}
public ObservableCollection<ContactVm> ContactsToDisplay 
{
    get { return _contactsToDisplay; }
    set
    {
        this._contactsToDisplay = value;
        NotifyPropertyChanged();
    }
}
private ContactVm _selectedContact;

public ContactVm SelectedContact
{
   set
   {
      if (_selectedContact!= value)
      {
          _selectedContact= value;

          SelectedContact.FirstName="Test";

          NotifyPropertyChanged("SelectedContact");
      }
   }
   get { return _selectedContact; }
}