将数据从 Main 发送到 Detail 并在 MainViewMode 中更新对象

Sending data from Main to Detail and Updating Object in MainViewMode

我有以下 recyclerview,其中包含 TestViewModel 个对象的列表。在这个对象中,我有 agegendername 属性。我正在尝试实现当用户单击列表项时,它会将用户带到详细视图,用户可以在其中更新并单击保存按钮,然后它会更新所选项目的属性。

问题:

当用户在详细信息中输入值并更新每个 属性、

时,我从 DetailViewModel 收到消息的 MainViewModel 中的以下代码段有效
private void OnMessageReceived(TestMessage obj)
{
    _selectedItem.Age = obj.messageTest.Age;
    _selectedItem.Name = obj.messageTest.Name;
    _selectedItem.Gender = obj.messageTest.Gender;
}

但是下面的代码在我尝试直接更新对象的地方不起作用。

private void OnMessageReceived(TestMessage obj)
{
    _selectedItem= obj.messageTest;
    RaisePropertyChanged(() => SelectedItem);
}

代码实现如下:

<MvxRecyclerView
    android:id="@+id/TestRecyclerView"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    local:MvxBind="ItemsSource TestsViews; ; ItemClick ItemSelected" /> 

MainViewModel

public MainViewModel SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        ShowViewModel<DetailViewModel>(
        new DetailViewModel.Parameter
        {
            Age = _selectedItem.Age,
            Name = _selectedItem.Name,
            Gender = _selectedItem.Gender,
        });
        RaisePropertyChanged(() => SelectedItem);
    }
}

public virtual ICommand ItemSelected
{
   get
    {
      return new MvxCommand<TestViewModel>(item =>
      {
          SelectedItem = item;
      });
     }
}

private void OnMessageReceived(TestMessage obj)
{
    _selectedItem.Age= obj.messageTest.Age;
    _selectedItem.Name= obj.messageTest.Name;
    _selectedItem.Gender= obj.messageTest.Gender;
 }

测试消息

public class TestMessage : MvxMessage
{
    public MainModel messageTest { get; set; }

    public TestMessage(object sender, MainModel editTest) : base(sender)
    {
        messageTest = editTest;
    }
}

DetailViewModel

public TestViewModel EditTest
{
    get { return _editTest; }
    set
    {
        _editTest = value;
        RaisePropertyChanged(() => EditTest);
    }
}

public DetailViewModel(IMvxMessenger messenger)
{
    _messenger = messenger;
}

public void Save()
{
    UpdateValues();
}

public void UpdateValues()
{
    var message = new TestMessage(this, _editTest);
    _messenger.Publish(message, typeof(TestMessage));
}

public void Init(Parameter param)
{
    _editTest = new TestViewModel();
    _editTest.Age = param.Age;
    _editTest.Name = param.Name;
    _editTest.Gender = param.Gender;

public class Parameter
{
    public double Age { get; set; }
    public int Gender { get; set; }
    public string Name { get; set; }
}

详细视图xml

<EditText
    style="@style/InputNumbersEditText"
    android:layout_weight="1"
    android:layout_width="0dp"
    android:layout_height="44dp"
    android:gravity="center_vertical|right"
    android:hint="00.000"
    local:MvxBind="Text EditTest.Age, Converter=Nullable;" />

TestViewModel

public class TestViewModel : BaseViewModel
{
    public string? Name { get; set; }
    public double? Age { get; set; }
    public int? Gender { get; set; }
}

NullableValueConverter

public class NullableValueConverter : MvxValueConverter
{
    public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (string.IsNullOrEmpty(value?.ToString()))
        {
            return parameter;
        }
        return value;
    }

    public override object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null || string.IsNullOrEmpty(value.ToString()))
        {
            return null;
        }

        return value;
    }
}

更新答案

_selectedItem 分配一个新的 TestViewModel 会破坏它对 TestsViews 数据源列表中保存的 TestViewModel 的引用 link。在分配各个属性时,会保留对 TestsViews 列表中原始 TestViewModel 的引用。

原答案

由于您正在更新支持字段 _selectedItem,因此当您收到消息事件时,SelectedItem 属性 集合中定义的 RaisePropertyChanged 事件将从来没有 运行。您必须手动触发 RaisePropertyChanged 才能触发绑定更新。

尝试改变您当前的方法:

private void OnMessageReceived(TestMessage obj)
{
    _selectedItem= obj.messageTest;
}

要引发 属性 更改事件:

private void OnMessageReceived(TestMessage obj)
{
    _selectedItem = obj.messageTest;
    RaisePropertyChanged(() => SelectedItem);
}
private void OnMessageReceived(TestMessage obj)
{
    _selectedItem= obj.messageTest;
    RaisePropertyChanged(() => SelectedItem);
}

这行不通,因为您只是将 _selectedItem 的引用更改为指向另一个对象。但是这个对象不包含在用于显示在回收站视图中的列表中。您不是更新对象,只是一个参考!你绝对应该看看 C# 的基础知识来理解这种数据结构。例如。 Reference vs. Value Type

您的代码有点错误。

  • SelectedItem 的类型是 MainViewModel
  • 您的点击命令获得类型为 TestViewModel

    的项目
    public virtual ICommand ItemSelected
    {
        get
        {
            return new MvxCommand<TestViewModel>(item =>
            {
                SelectedItem = item;
            });
        }
    } 
    

通常这应该有效:

private void OnMessageReceived(TestMessage obj)
{
    _selectedItem.Age= obj.messageTest.Age;
    _selectedItem.Name= obj.messageTest.Name;
    _selectedItem.Gender= obj.messageTest.Gender;
}

但是 TestViewModel

public class TestViewModel : BaseViewModel
{
    private string? name;
    public string? Name { get{ return name; } set { SetProperty(ref name, value); } }
    // same for Age and Gender
}

SetProperty 设置值并调用 OnPropertyChanged 事件。