Data binding 将数据从Main发送到Detail,并在MainViewMode中更新对象
我有下面的Data binding 将数据从Main发送到Detail,并在MainViewMode中更新对象,data-binding,xamarin,xamarin.android,mvvmcross,Data Binding,Xamarin,Xamarin.android,Mvvmcross,我有下面的recyclerview,其中包含TestViewModel对象列表。在这个对象中,我有年龄、性别和姓名属性。我试图实现当用户单击列表项时,它将用户带到详细视图,用户可以在其中更新并单击保存按钮,然后更新所选项的属性 问题: <MvxRecyclerView android:id="@+id/TestRecyclerView" android:scrollbars="vertical" android:layout_width="match_parent"
recyclerview
,其中包含TestViewModel
对象列表。在这个对象中,我有年龄
、性别
和姓名
属性。我试图实现当用户单击列表项时,它将用户带到详细视图,用户可以在其中更新并单击保存按钮,然后更新所选项的属性
问题:
<MvxRecyclerView
android:id="@+id/TestRecyclerView"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
local:MvxBind="ItemsSource TestsViews; ; ItemClick ItemSelected" />
在MainViewModel
中,当用户在细节中输入值并更新每个属性时,我从DetailViewModel
接收消息的下面一段代码将起作用
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" />
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; }
}
<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;" />
详细视图xml
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; }
}
<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;" />
NullableValueConverter
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;
}
}
public class TestViewModel : BaseViewModel
{
public string? Name { get; set; }
public double? Age { get; set; }
public int? Gender { get; set; }
}
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;
}
}
更新的答案 为
\u selectedItem
分配一个新的TestViewModel
会断开它与TestsViews
数据源列表中的TestViewModel
的参考链接。分配各个属性时,会在TestsViews
列表中维护对原始TestViewModel
的引用
原始答案
更新支持字段时,\u selectedItem
,因此当您收到消息事件时,selectedItem
属性集中定义的RaisePropertyChanged
事件将永远不会运行。您必须手动触发RaisePropertyChanged
,才能触发绑定更新
尝试更改当前的方法:
private void OnMessageReceived(TestMessage obj)
{
_selectedItem= obj.messageTest;
}
要引发属性更改事件,请执行以下操作:
private void OnMessageReceived(TestMessage obj)
{
_selectedItem = obj.messageTest;
RaisePropertyChanged(() => SelectedItem);
}
更新的答案 为
\u selectedItem
分配一个新的TestViewModel
会断开它与TestsViews
数据源列表中的TestViewModel
的参考链接。分配各个属性时,会在TestsViews
列表中维护对原始TestViewModel
的引用
原始答案
更新支持字段时,\u selectedItem
,因此当您收到消息事件时,selectedItem
属性集中定义的RaisePropertyChanged
事件将永远不会运行。您必须手动触发RaisePropertyChanged
,才能触发绑定更新
尝试更改当前的方法:
private void OnMessageReceived(TestMessage obj)
{
_selectedItem= obj.messageTest;
}
要引发属性更改事件,请执行以下操作:
private void OnMessageReceived(TestMessage obj)
{
_selectedItem = obj.messageTest;
RaisePropertyChanged(() => SelectedItem);
}
这不起作用,因为您正在将\u selectedItem
的引用更改为指向另一个对象。但此对象不包括在用于在“回收器”视图中显示的列表中。您不是在更新对象,只是在更新引用!为了理解这种数据结构,您一定要了解C#的基础知识。例如
你的代码有点错误
- 您
的类型为SelectedItem
MainViewModel
- 单击命令将获得类型为
TestViewModel
但是使用public virtual ICommand ItemSelected { get { return new MvxCommand<TestViewModel>(item => { SelectedItem = item; }); } }
之类的TestViewModel
public class TestViewModel : BaseViewModel { private string? name; public string? Name { get{ return name; } set { SetProperty(ref name, value); } } // same for Age and Gender }
设置值并调用OnPropertyChanged事件 这不起作用,因为您正在将SetProperty
的引用更改为指向另一个对象。但此对象不包括在用于在“回收器”视图中显示的列表中。您不是在更新对象,只是在更新引用!为了理解这种数据结构,您一定要了解C#的基础知识。例如 你的代码有点错误\u selectedItem
- 您
的类型为SelectedItem
MainViewModel
- 单击命令将获得类型为
TestViewModel
但是使用public virtual ICommand ItemSelected { get { return new MvxCommand<TestViewModel>(item => { SelectedItem = item; }); } }
之类的TestViewModel
public class TestViewModel : BaseViewModel { private string? name; public string? Name { get{ return name; } set { SetProperty(ref name, value); } } // same for Age and Gender }
设置值并调用OnPropertyChanged事件。TestsView(MainViewModel的属性)是什么样子的?它是什么类型的?我刚刚编辑了这个问题。SetProperty
(MainViewModel的属性)是什么样子的?它是什么类型的?我刚刚编辑了这个问题。我认为这个问题可能是TestsViews
的TestMessage
(messageTest
)属性的分配是一个新对象(具有不同的引用),因此当它被分配时,它不再能够从RecyclerView更新TestViewModel
。这解释了为什么在分配单个属性时它会起作用,因为它们基于仍然链接到RecyclerView的selectedItem
。我认为问题可能在于selectedItem
的TestMessage
(messageTest
)属性的分配是一个新对象(具有不同的引用)因此,当它被分配时,它不再能够从RecyclerView更新TestViewModel
。这解释了为什么当您分配单个属性时它会起作用,因为它们基于仍然链接到RecyclerView的selectedItem
。selectedItem
- 您