将数据从 Main 发送到 Detail 并在 MainViewMode 中更新对象
Sending data from Main to Detail and Updating Object in MainViewMode
我有以下 recyclerview
,其中包含 TestViewModel
个对象的列表。在这个对象中,我有 age
、gender
和 name
属性。我正在尝试实现当用户单击列表项时,它会将用户带到详细视图,用户可以在其中更新并单击保存按钮,然后它会更新所选项目的属性。
问题:
当用户在详细信息中输入值并更新每个 属性、
时,我从 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 事件。
我有以下 recyclerview
,其中包含 TestViewModel
个对象的列表。在这个对象中,我有 age
、gender
和 name
属性。我正在尝试实现当用户单击列表项时,它会将用户带到详细视图,用户可以在其中更新并单击保存按钮,然后它会更新所选项目的属性。
问题:
当用户在详细信息中输入值并更新每个 属性、
时,我从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 事件。