mvvm从加载的视图模型交叉执行方法

问题描述

如何在已加载的视图模型中执行方法?
我的结构;

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,我们要在其中显示三个标签:TabOneViewModelTabTwoViewModelTabThreeViewModel。所有这些选项卡视图模型都实现一个ITabViewModel界面。 TabControlPivot类的自定义实现,它显示了不同的选项卡视图,并且还确定是否应重新加载导航到的选项卡。

TabHostViewModelITabViewModel

// 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"

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...