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

mvvm Cross execute methods from a loaded viewmodel

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

MainView(TabControl) - MainViewModel
View1(Tab1) - ViewModel1
View2(Tab2) - ViewModel2
View3(Tab3) - ViewModel3

在每个 ViewModel 中都有一个 ReloadData() 方法,它从我的数据库中加载一些数据。他们已经像这样在构造函数中被解雇了;

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 class 的自定义实现,它显示不同的选项卡视图并确定是否应重新加载导航到的选项卡。

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)
            },
            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; }
}

自定义 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;
    }
}

在你的 TabHostView:

中使用 TabControl
<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"