问题描述
如何在已加载的视图模型中执行方法?
我的结构;
MainView(TabControl) - MainViewModel
View1(Tab1) - ViewModel1
View2(Tab2) - ViewModel2
View3(Tab3) - ViewModel3
在每个ViewModel中,都有一个ReloadData()-Method,它从我的数据库中加载一些数据。它们已经像这样在构造函数中被解雇了;
public ViewModel1()
{
ReloadData();
}
private async void ReloadData(){ }
导航到MainViewModel时,它将直接(在ViewAppeared-Method中)导航到选项卡;
this._navigationService.Navigate<ViewModel1>();
this._navigationService.Navigate<ViewModel2>();
this._navigationService.Navigate<ViewModel3>();
我想在WPF项目和移动版本中使用此重新加载程序实现。
解决方法
您可以尝试使用IMvxMessenger
并在需要重新加载数据时发布事件。有关的TabViewModels订阅该事件并在调用时调用ReloadData()
。
我看到的另一种实现方式是这样的。
您有一个TabHostViewModel
,其视图包含一个TabControl
,我们要在其中显示三个标签:TabOneViewModel
,TabTwoViewModel
和TabThreeViewModel
。所有这些选项卡视图模型都实现一个ITabViewModel
界面。
TabControl
是Pivot
类的自定义实现,它显示了不同的选项卡视图,并且还确定是否应重新加载导航到的选项卡。
TabHostViewModel
和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)
},ViewModelType = typeof(TabThreeViewModel)
}
};
}
}
public class TabPage
{
public string Title { get; set; }
public Type ViewModelType { get; set; }
public ITabViewModel ViewModelInstance { get; set; }
}
自定义TabControl
类:
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;
}
}
在您的TabControl
中使用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>
请注意,您需要指定选项卡控件的位置,因此还需要在TabHostView
中添加以下内容:
xmlns:controls="using:NAMESPACE_OF_TABCONTROL_HERE"