How can I execute methods in a loaded view model?
my strucuture;
MainView(TabControl) - MainViewModel
View1(Tab1) - ViewModel1
View2(Tab2) - ViewModel2
View3(Tab3) - ViewModel3
Inside every ViewModel there are a ReloadData()-Method, that load some data from my database. They already get fired in the constructor like so;
public ViewModel1()
{
ReloadData();
}
private async void ReloadData(){ }
When navigating to the MainViewModel it will directly(in the ViewAppeared-Method) navigate to the tabs;
this._navigationService.Navigate<ViewModel1>();
this._navigationService.Navigate<ViewModel2>();
this._navigationService.Navigate<ViewModel3>();
I want to use this reloader-implemenation in my WPF project and in my mobile versions.
What you could try is using IMvxMessenger
and publish an event when data needs to be reloaded. The concerning TabViewModels subscribe to that event and call ReloadData()
when invoked.
Another way I have seen this implemented is like this.
You have a TabHostViewModel
and its view contains a TabControl
in which we want to display three tabs: TabOneViewModel
, TabTwoViewModel
and TabThreeViewModel
. All these tab view models implement an ITabViewModel
interface.
The TabControl
is a custom implementation of the Pivot
class which shows the different tab views and also determines whether the tab to which is navigated should be reloaded.
TabHostViewModel
and ITabViewModel
:
// TabOneViewModel, TabTwoViewModel and TabThreeViewModel should implement this
public interface ITabViewModel
{
bool ShouldReloadBeforeShow { get; }
// This method should reload whatever needs to be reloaded in your ViewModel
void ReloadModel();
}
public class TabHostViewModel : MvxViewModel
{
public IList<TabPage> TabPages { get; set;}
public override Task Initialize()
{
TabPages = new List<TabPage>
{
new TabPage {
Title = "Tab one",
ViewModelType = typeof(TabOneViewModel)
},
new TabPage {
Title = "Tab one",
ViewModelType = typeof(TabTwoViewModel)
},
new TabPage {
Title = "Tab one",
ViewModelType = typeof(TabThreeViewModel)
}
};
}
}
public class TabPage
{
public string Title { get; set; }
public Type ViewModelType { get; set; }
public ITabViewModel ViewModelInstance { get; set; }
}
Custom TabControl
class:
public class TabControl : Pivot
{
private readonly IMvxViewsContainer _mvxViewsContainer;
private readonly IMvxViewModelLoader _mvxViewModelLoader;
public TabControl()
{
Loaded += TabControl_Loaded;
SelectionChanged += TabControl_SelectionChanged;
_mvxViewsContainer = Mvx.IoCProvider.Resolve<IMvxViewsContainer>();
_mvxViewModelLoader = Mvx.IoCProvider.Resolve<IMvxViewModelLoader>();
}
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selectedTab = (TabPage) SelectedItem;
if (selectedTab.ViewModelInstance != null && selectedTab.ViewModelInstance.ShouldReloadBeforeShow)
selectedTab.ViewModelInstance.ReloadModel();
}
private void TabControl_Loaded(object sender, RoutedEventArgs e)
{
foreach (var item in Items)
{
var tabPage = item as TabPage;
var view = CreateViewByViewModelType(tabPage.ViewModelType);
var viewModel = CreateViewModelByViewModelType(tabPage.ViewModelType);
tabPage.ViewModelInstance = viewModel;
view.ViewModel = viewModel;
tabPage.View = view;
}
Loaded -= TabControl_Loaded;
}
private MvxWindowsView CreateViewByViewModelType(Type viewModelType)
{
var viewType = _mvxViewsContainer.GetViewType(viewModelType);
if (viewType == null)
throw new MvxException("View Type not found for " + viewModelType);
var viewObject = Activator.CreateInstance(viewType);
if (viewObject == null)
throw new MvxException("View not loaded for " + viewType);
var view = viewObject as IMvxWindowsView;
if (view == null)
throw new MvxException("Loaded View is not a IMvxWindowsView " + viewType);
return view;
}
public IMvxViewModel CreateViewModelByViewModelType(Type viewModelType)
{
var viewModelRequest = new MvxViewModelRequest(viewModelType);
var viewModel = _mvxViewModelLoader.LoadViewModel(viewModelRequest, null);
return viewModel;
}
}
Use the TabControl
in your TabHostView
:
<controls:TabControl x:Name="TabHostControl" ItemsSource="{Binding TabPages}">
<controls:TabControl.HeaderTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock Text="{Binding Title}" FontSize="15" />
</StackPanel>
</DataTemplate>
</controls:TabControl.HeaderTemplate>
<controls:TabControl.ItemTemplate>
<DataTemplate>
<ContentPresenter VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="{Binding View}" />
</DataTemplate>
</controls:TabControl.ItemTemplate>
</controls:TabControl>
Note that you need to specify where the tab control is located so you need to also add the following to the TabHostView
:
xmlns:controls="using:NAMESPACE_OF_TABCONTROL_HERE"