2013-07-25 1 views
2

Кто-нибудь знает, как просмотреть существующий IMvxViewModel?Просмотр уже созданного ViewModel в MVVMCross

В моем приложении я уже создал кучу ViewModels (PhotoViewModel) внутри другой модели представления. Они существуют как свойство родительского ViewModel (AlbumViewModel). Было бы очень просто показать конкретный экземпляр PhotoViewModel вместо создания нового экземпляра этой модели представления, когда я захочу ее просмотреть.

public class AlbumViewModel : MvxViewModel { 
    public ObservableCollection<PhotoViewModel> Photos 
    { 
     get { return GetValue(() => Photos); } 
     set { SetValue(value,() => Photos); } 
    } 
} 

public class PhotoViewModel : MvxViewModel { } 

мне было интересно, если есть способ, другой, то создавая свой собственный IMvxViewModelLocator, чтобы выполнить эту задачу. Я думаю, что наличие защищенного метода в MvxNavigationObject под названием View может быть действительно полезным как для новых разработчиков, использующих фреймворк, так и для производительности. Мы могли бы пропустить все отражения, сделанные в настоящее время для создания модели представления.

ответ

1

по умолчанию ShowViewModel механизм MvvmCross использует страницы на основе навигации - это навигация должна использовать Uri с на WindowsPhone и Intent с на Android.

Из-за этого MvvmCross не разрешает навигацию по «богатым» объектам - простые сериализуемые POCOs - это нормально, но сложные «богатые» объекты не поддерживаются.

Это также важно из-за «гробницы» - если ваше приложение/страница/деятельность позже регидратированы, вы не можете быть уверены в том, какие исторические объекты View или ViewModel действительно находятся в вашем стеке истории «назад».


Если вы хотите, чтобы перемещаться по богатому объекту, то лучший способ для хранения этих богатых объектов в службе поиска и затем перемещаться по некоторому ключу/индекс в поиск. Тем не менее, я бы лично назвать те lookedup объектов Model сек, а не ViewModel с (но граница иногда не размывается!)


Хотя на основе MvvmCross v1 кода, этот вопрос все еще дает довольно хороший фон для этого - What is the best way to pass objects to "navigated to" viewmodel in MVVMCross?

Некоторые более уточненный объяснения включают:


Одна заключительная вещь ....

... манифестом MvvmCross настаивает, что MvvmCross очень открыта для настройки ...

Из-за этого вы можете переопределить навигацию MvvmCross и просмотреть местоположение модели, если хотите. Для этого создание вашего собственного IMvxViewModelLocator, вероятно, будет хорошим началом.

+0

Стюарт, большое вам спасибо за помощь. Я действительно шел по описанной вами дороге, и я думаю, что придумал решение, которое работает достаточно хорошо. Я изменил свой вопрос, чтобы показать предлагаемое решение. Хотелось бы услышать ваши мысли об этом. Еще раз спасибо за вашу помощь. – Joe

1

После некоторых испытаний ниже предлагается предлагаемое решение. Я не на 100% влюблен в него, но он действительно работает и предоставляет опыт разработчиков типов, которые я искал. Итак, давайте заглянем.

Для начала все мои модели ViewModels (VM) наследуют от базы VM, AVM.Этот абстрактный базовый класс поддерживает поиск объекта как общедоступного статического метода. Это немного грубо, но это хорошо работает, если вы хотите потягивать Kool-Aid. Ниже приводится часть класса, это отношение к этой проблеме:

public abstract class AVM : MvxViewModel { 
    private static readonly Dictionary<Guid, WeakReference> ViewModelCache = new Dictionary<Guid, WeakReference>(); 
    private static readonly string BUNDLE_PARAM_ID = @"AVM_ID"; 

    private Guid AVM_ID = Guid.NewGuid(); 
    private Type MyType; 

    protected AVM() 
    { 
     MyType = this.GetType(); 
     ViewModelCache.Add(AVM_ID, new WeakReference(this)); 
    } 

    public static bool TryLoadFromBundle(IMvxBundle bundle, out IMvxViewModel viewModel) 
    { 
     if (null != bundle && bundle.Data.ContainsKey(BUNDLE_PARAM_ID)) 
     { 
      var id = Guid.Parse(bundle.Data[BUNDLE_PARAM_ID]); 
      viewModel = TryLoadFromCache(id); 
      return true; 
     } 

     viewModel = null; 

     return false; 
    } 

    private static IMvxViewModel TryLoadFromCache(Guid Id) 
    { 
     if (ViewModelCache.ContainsKey(Id)) 
     { 
      try 
      { 
       var reference = ViewModelCache[Id]; 
       if (reference.IsAlive) 
        return (IMvxViewModel)reference.Target; 
      } 
      catch (Exception exp) { Mvx.Trace(exp.Message); } 
     } 

     return null; 
    } 


    protected void View() 
    { 
     var param = new Dictionary<string, string>(); 
     param.Add(BUNDLE_PARAM_ID, AVM_ID.ToString()); 
     ShowViewModel(MyType, param); 
    } 

Для того, чтобы получить все это проводной, вы должны создать пользовательский вид модели локатора. Вот пользовательский локатор:

public class AVMLocator : MvxDefaultViewModelLocator 
{ 
    public override bool TryLoad(Type viewModelType, IMvxBundle parameterValues, IMvxBundle savedState, out IMvxViewModel viewModel) 
    { 
     if (AVM.TryLoadFromBundle(parameterValues, out viewModel)) 
      return true; 
     return base.TryLoad(viewModelType, parameterValues, savedState, out viewModel); 
    } 
} 

Наконец, вам нужно подключиться. Для этого перейдите в ваш App.cs и переопределить CreateDefaultViewModelLocator следующим образом:

protected override IMvxViewModelLocator CreateDefaultViewModelLocator() 
    { 
     return new AVMLocator(); 
    } 

Ты весь набор. Теперь в любом из полученных ViewModels, которые уже живы и здоровы, вы можете сделать следующее:

myDerivedVM.View(); 

Там еще некоторые более мне нужно сделать (например, убедившись, что WeakReferences делать свою работу, и у меня нет утечки памяти и некоторая дополнительная обработка ошибок), но, по крайней мере, это тот опыт, который я собирался сделать. Последнее, что я сделал, добавьте следующую команду в базовый класс АВМ:

public MvxCommand ViewCommand 
{ 
    get { return new MvxCommand(View); } 
} 

Теперь вы можете связать эту команду к любому объекту пользовательского интерфейса и при вызове, он будет запускать эту точку зрения с той самой экземпляр виртуальной машины ,

Стюарт, спасибо за помощь в управлении мной в правильном направлении. Мне было бы интересно услышать ваши отзывы о решении, которое я вам предоставил. Спасибо за всю вашу работу с MVVMCross. Это действительно красивый код.

Cheers.