Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Data binding 将数据从Main发送到Detail,并在MainViewMode中更新对象_Data Binding_Xamarin_Xamarin.android_Mvvmcross - Fatal编程技术网

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
    }
    
    SetProperty
    设置值并调用OnPropertyChanged事件

    这不起作用,因为您正在将
    \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
      }
      

      SetProperty
      设置值并调用OnPropertyChanged事件。

      TestsView(MainViewModel的属性)是什么样子的?它是什么类型的?我刚刚编辑了这个问题。
      TestsViews
      (MainViewModel的属性)是什么样子的?它是什么类型的?我刚刚编辑了这个问题。我认为这个问题可能是
      TestMessage
      messageTest
      TestViewModel
      )属性的分配是一个新对象(具有不同的引用),因此当它被分配时,它不再能够从RecyclerView更新
      selectedItem
      。这解释了为什么在分配单个属性时它会起作用,因为它们基于仍然链接到RecyclerView的
      selectedItem
      。我认为问题可能在于
      TestMessage
      messageTest
      TestViewModel
      )属性的分配是一个新对象(具有不同的引用)因此,当它被分配时,它不再能够从RecyclerView更新
      selectedItem
      。这解释了为什么当您分配单个属性时它会起作用,因为它们基于仍然链接到RecyclerView的
      selectedItem