2016-04-23 5 views
0

Ich habe die folgenden recyclerview, wo es eine Liste von TestViewModel Objekte enthält. In diesem Objekt habe ich age, gender und name Eigenschaften. Ich versuche zu erreichen, wenn der Benutzer auf ein Listenelement klickt, den Benutzer in die Detailansicht bringt, in der der Benutzer aktualisieren kann, und auf die Schaltfläche zum Speichern klickt, dann aktualisiert er die ausgewählten Elementeigenschaften.Senden von Daten von Main zu Detail und Aktualisieren von Objekt in MainViewMode

Ausgabe:

Das folgende Stück Code in MainViewModel, wo ich die Nachricht von DetailViewModel Werken erhalten, wenn der Benutzer Wert im Detail eingeben und jede Eigenschaft zu aktualisieren,

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

aber die folgende Stück Code funktioniert nicht, wo ich versuche, das Objekt selbst direkt zu aktualisieren.

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

Code-Implementierung ist wie folgt:

<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; 
} 

Testmessage

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; } 
} 

Detailview 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; 
    } 
} 
+0

Wie sieht 'TestsViews' (die Eigenschaft des MainViewModels) aus? Welcher Typ hat es? –

+0

Ich habe gerade die Frage bearbeitet. – hotspring

Antwort

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

Dies kann nicht funktionieren, weil Ihr nur verändern die Referenz von _selectedItem zu auf ein anderes Objekt zeigen. Dieses Objekt ist jedoch nicht in der Liste enthalten, die in der Recycleransicht angezeigt wird. Sie sind nicht Aktualisieren eines Objekts, nur eine Referenz! Sie sollten sich unbedingt die Grundlagen von C# ansehen, um diese Art von Datenstruktur zu verstehen. Z.B. Reference vs. Value Type

Ihr Code ist ein bisschen fehlerhaft.

  • Sie SelectedItem hat den Typ MainViewModel
  • Ihr Klickbefehl ein Element des Typs erhält diese sollte TestViewModel

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

Normalerweise arbeiten:

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

aber mit einem TestViewModel wie

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

SetProperty setzt den Wert und ruft die OnPropertyChanged Ereignis.

0

aktualisiert Antwort

Zuordnung der _selectedItem eine neue TestViewModel bricht die Referenzverbindung an die TestViewModel in der TestsViews Datenquelle Liste gehalten hat. Bei der Zuordnung der einzelnen Eigenschaften bleibt der Verweis auf das Original TestViewModel in der TestsViews Liste erhalten.

ORGINAL

Antwort Wie Sie das dahinter liegende Feld aktualisieren, _selectedItem, so dass, wenn Sie die Meldung Ereignis das RaisePropertyChanged Ereignis in der Ihrer SelectedItem Eigenschaft wird nie ausgeführt definiert erhalten. Sie müssen das RaisePropertyChanged manuell auslösen, um das Bindungsupdate auszulösen.

Versuchen Sie, Ihre aktuelle Methode zu ändern:

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

die Eigenschaft veränderte Ereignis auszulösen:

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

Ich habe versucht, aber es hat nicht funktioniert. – hotspring

+0

Ich denke, das Problem möglicherweise die Zuordnung der 'TestMessage'' 'messageTest' (' TestViewModel') -Eigenschaft ist ein neues Objekt (hat eine andere Referenz) und daher, wenn es zugewiesen wird, ist es nicht mehr in der Lage, das 'selectedItem zu aktualisieren 'aus der RecyclerView. Dies erklärt, warum es funktioniert, wenn Sie einzelne Eigenschaften zuweisen, da sie auf dem 'selectedItem' basieren, das immer noch mit dem RecyclerView verbunden ist. – Plac3Hold3r