2015-07-02 4 views
1

Я попытался связать свойство настраиваемого типа в View Model с пользовательским представлением, но в методе Binder значение «SetValue (object value)» всегда равно null. Почему так происходит? Невозможно ли связать свойство пользовательского типа с пользовательским представлением в MvvmCross?MvvmCross свойство привязки настраиваемого типа к пользовательскому виду

Мои ViewModel:

public class RecipesFiltersVM : MvxViewModel 
{ 
    public SearchField DishField { get; private set; } 
    public SearchField CuisineField { get; private set; } 
    public SearchField IngredientField { get; private set; } 

    private readonly IFiltersService _filtersService; 

    public RecipesFiltersVM(IFiltersService filtersService) 
    { 
     _filtersService = filtersService; 

     UpdateSearchFields(); 
    } 

    private async void UpdateSearchFields() 
    { 
     var allFilters = await _filtersService.LoadAllFilters(); 

     DishField = new SearchField (
      allFilters 
      .Where(f => f.Type == FilterType.Dish) 
      .ToList() 
     ); 
     CuisineField = new SearchField (
      allFilters 
      .Where(f => f.Type == FilterType.Cuisine) 
      .ToList() 
     ); 
     IngredientField = new SearchField (
      allFilters 
      .Where(f => f.Type == FilterType.Ingredient) 
      .ToList() 
     ); 
    } 
} 

Мой SearchField:

public class SearchField : MvxViewModel 
{ 
    private String _searchResult; 
    public String SearchResult { 
     get { return _searchResult; } 
     set { 
      _searchResult = value; 
      RaisePropertyChanged (() => SearchResult); 
      UpdateFoundFilters(); 
     } 
    } 

    private ObservableCollection<Filter> _foundFilters; 
    public ObservableCollection<Filter> FoundFilters { 
     get { return _foundFilters; } 
     set { 
      _foundFilters = value; 
      RaisePropertyChanged (() => FoundFilters); 
     } 
    } 
} 

В CustomView:

public class SearchFieldView : UIView 
{ 
    public UITextField SearchResult { get { return _searchResult; } } 
    private UITextField _searchResult; 

    public UITableView FoundFilters { get { return _foundFilters; } } 
    private UITableView _foundFilters; 
} 

В Binder:

public class SearchFieldViewWithSearchFieldBinder : MvxTargetBinding 
{ 
    protected SearchFieldView SearchFieldView { 
     get { return (SearchFieldView)Target; } 
    } 

    public SearchFieldViewWithSearchFieldBinder (SearchFieldView target) 
     : base (target) 
    { 

    } 

    public override void SetValue (object value) 
    { 
     //value is always null! 
    } 

    public override Type TargetType { 
     get 
     { 
      return typeof(SearchField); 
     } 
    } 

    public override MvxBindingMode DefaultMode { 
     get 
     { 
      return MvxBindingMode.TwoWay; 
     } 
    } 
} 

установки:

protected override void FillTargetFactories (Cirrious.MvvmCross.Binding.Bindings.Target.Construction.IMvxTargetBindingFactoryRegistry registry) 
    { 
     registry.RegisterCustomBindingFactory<SearchFieldView> (
      "SearchField", 
      indicators => new SearchFieldViewWithSearchFieldBinder(indicators) 
     ); 
     base.FillTargetFactories (registry); 
    } 

В ViewController:

var set = this.CreateBindingSet<RecipesFiltersDialog, RecipesFiltersVM>(); 
set.Bind (_dish).For("SearchField").To (vm => vm.DishField); 
set.Bind (_cuisine).For("SearchField").To (vm => vm.CuisineField); 
set.Bind (_ingredient).For("SearchField").To (vm => vm.IngredientField); 
set.Apply(); 

UPD

решаемые с двумя способами обновить ViewModel код. Во-первых, я изменил таможенную декларацию собственности, как: выполнение

private SearchField _dishField; 
    public SearchField DishField { 
     get 
     { 
      return _dishField; 
     } 
     set 
     { 
      _dishField = value; 
      RaisePropertyChanged (() => DishField); 
     } 
    } 

Во-вторых, я инициализировать свои свойства в ViewModel конструктора до того UpdateSearchFields():

public RecipesFiltersVM(IFiltersService filtersService) 
    { 
     _filtersService = filtersService; 

     DishField = new SearchField (new List<Filter>()); 
     CuisineField = new SearchField (new List<Filter>()); 
     IngredientField = new SearchField (new List<Filter>()); 

     UpdateSearchFields(); 
    } 
+0

Вы можете разместить еще больше кода? например полная модель просмотра, показывающая, где DishField установлен на ненулевое значение? Что-то вроде видео N + 1 MvxView также может помочь в альтернативном подходе - https://github.com/MvvmCross/NPlus1DaysOfMvvmCross/blob/master/N-32-ViewModels/Compo.Touch/Views/FirstView.cs – Stuart

+0

@Stuart Я добавил больше кода в ViewModel, и я увидел свою проблему. Спасибо за ответ, очень полезно – Pocheshire

ответ

0

Удовлетворительно с Stuart's Комментарий двумя способами обновляется ViewModel code. Во-первых, я изменил таможенную декларацию собственности, как:

private SearchField _dishField; 
    public SearchField DishField { 
     get 
     { 
      return _dishField; 
     } 
     set 
     { 
      _dishField = value; 
      RaisePropertyChanged (() => DishField); 
     } 
    } 

Второй инициализирую свои свойства в ViewModel конструктора до того UpdateSearchFields() исполнение:

public RecipesFiltersVM(IFiltersService filtersService) 
    { 
     _filtersService = filtersService; 

     DishField = new SearchField (new List<Filter>()); 
     CuisineField = new SearchField (new List<Filter>()); 
     IngredientField = new SearchField (new List<Filter>()); 

     UpdateSearchFields(); 
    } 
0

Вы должны создать свои собственные привязки для пользовательской точки зрения. Например, если вы следовали нормальной MvvmCross практике использования свойств # общественности C и C# события для определения элементов в пользовательской точке зрения, то вы должны быть в состоянии сделать что-то вроде этого:

public class SearchFieldView : UIView, IMvxBindable 
{ 
    public IMvxBindingContext BindingContext { get; set; } 

    public SearchFieldView() 
    { 
     this.CreateBindingContext(); 
    } 

    public UITextField SearchResult { get { return _searchResult; } } 
    private UITextField _searchResult; 

    public UITableView FoundFilters { get { return _foundFilters; } } 
    private UITableView _foundFilters; 

    [MvxSetToNullAfterBinding] 
    public object DataContext 
    { 
     get { return BindingContext.DataContext; } 
     set { BindingContext.DataContext = value; } 
    } 

    protected override void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      BindingContext.ClearAllBindings(); 
     } 
     base.Dispose(disposing); 
    } 
} 

И тогда он должен просто " Работа." Для вдохновения проверьте вещи вроде MvxView или MvxTableViewCell.


В качестве альтернативы вы можете быть в состоянии сделать свой собственный MvxPropertyInfoTargetBinding как то, как MvvmCross обрабатывает в UISegmentedControlBindings путем реализации что-то вроде MvxUISegmentedControlSelectedSegmentTargetBinding.

+0

спасибо за ответ, но решение было немного проще – Pocheshire

 Смежные вопросы

  • Нет связанных вопросов^_^