Reputation: 41
I searched for quite a time, and didn't found any case to match the problem I'm currently facing.
I have a subclass of MvxFragmentActivity (MainRootView.cs/.axml) that contains an Android navigation drawer layout:
public class MainRootView : MvxFragmentActivity, IFragmentHost
{
...
protected override void OnViewModelSet ()
{
base.OnViewModelSet ();
SetContentView (Resource.Layout.MainRootView);
...
}
In Setup.cs I defined a custom Presenter to control what fragment is shown when a new viewModel get loaded:
public interface IFragmentHost
{
bool Show (MvxViewModelRequest request);
}
public interface ICustomPresenter
{
void Register (Type viewModelType, IFragmentHost host);
}
public class CustomPresenter : MvxAndroidViewPresenter, ICustomPresenter
{
private Dictionary<Type, IFragmentHost> dictionary = new Dictionary<Type, IFragmentHost>();
public override void Show (MvxViewModelRequest request)
{
IFragmentHost host;
if (this.dictionary.TryGetValue (request.ViewModelType, out host))
{
if (host.Show (request))
{
return;
}
}
base.Show (request);
}
public void Register(Type viewModelType, IFragmentHost host)
{
this.dictionary [viewModelType] = host;
}
}
Now - in MainRootView.cs - I implemented the Show method for a certain ViewModelRequest, and replace the framelayout content with a certain fragment:
public bool Show(Cirrious.MvvmCross.ViewModels.MvxViewModelRequest request)
{
if (request.ViewModelType == typeof(OneCertainViewModel))
{
var loaderService = Mvx.Resolve<IMvxViewModelLoader> ();
var viewModel = loaderService.LoadViewModel (request, null);
var oneCertainFragment = new OneCertainFragment ();
oneCertainFragment.ViewModel = viewModel;
var ft = SupportFragmentManager.BeginTransaction ();
ft.Replace (Resource.Id.flMainContent, oneCertainFragment);
ft.Commit ();
return true;
}
...
}
The fragment code looks like this:
public class HubFragment : MvxFragment
{
...
public override global::Android.Views.View OnCreateView(global::Android.Views.LayoutInflater inflater,
global::Android.Views.ViewGroup container,
Bundle savedInstanceState)
{
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
global::Android.Views.View view = this.BindingInflate(Resource.Layout.HubFragment, null);
return view;
}
...
This fragment contains a small number of dynamically created custom subviews, each one being related to a separate viewmodel, that is being set right after its creation.
public class SubSectionView : LinearLayout, IHubSectionView
{
private MySubViewModel _vm;
public void SetContentViewModel (MySubViewModel vm)
{
_vm = vm;
...
}
Now how can bind a property of a TextView inside of this subview to a property of the viewModel I have set before, if that's possible at all?
Thanks a lot for any advice!
Upvotes: 4
Views: 1721
Reputation: 125
As I hope to understand your case, I've had your problem in quite same form:
I have a ViewModel with another SubViewModel as a property; let's call it: MySubView
Assume that we have a main view like this:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<Mvx.MvxFrameControl
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxBind="DataContext MySubView"
local:MvxTemplate="@layout/subview"/>
...
</RelativeLayout>
Using MvxFrameControl is the key here. It binds our property and pass it to specified template. There we may use our SubViewModel's properties.
So all we need is to define MySubView
in our main viewmodel:
public class MainViewModel : MvxViewModel
{
...
private SubViewModel _mySubView = new SubViewModel();
public SubViewModel MySubView
{
get { return _mySubView; }
set { _mySubView = value; RaisePropertyChanged(() => MySubView); }
}
...
}
Hope it helps.
Upvotes: 1