问题
I'm pretty new in MvvmCross
but I'm working with mvvm
for awhile. I know how to compose usercontrols with nested usercontrols. Now with mvvmcross
I got stucked to show two or more usercontrols in another usercontrol. I don't use any other framework than MvvmCross
.
My Rootview looks like this:
`<views:MvxWpfView
x:Class="MvvmCrossTest.Wpf.Views.RootView"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<DockPanel>
<TextBlock Text="Root" DockPanel.Dock="Top"/>
<ContentControl x:Name="MainMenuVM" Content="{Binding MainMenuVM}" DockPanel.Dock="Top" />
</DockPanel>
</views:MvxWpfView>`
The corresponding ViewModel looks like this:
using MvvmCross.Commands;
using MvvmCross.Logging;
using MvvmCross.Navigation;
using MvvmCross.ViewModels;
namespace MvvmCrossTest.Core.ViewModels
{
public class RootViewModel: MvxNavigationViewModel
{
private readonly IMvxViewModelLoader _mvxViewModelLoader;
public RootViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService, IMvxViewModelLoader mvxViewModelLoader) : base(logProvider, navigationService)
{
_mvxViewModelLoader = mvxViewModelLoader;
ShowMainMenu();
}
private MainMenuViewModel _mainMenuVM;
public MainMenuViewModel MainMenuVM
{
get { return _mainMenuVM; }
set
{
SetProperty(ref _mainMenuVM, value);
RaisePropertyChanged(() => MainMenuVM);
}
}
public MvxCommand ShowMainMenuCommand { get; set; }
public void ShowMainMenu()
{
MainMenuVM = (MainMenuViewModel)_mvxViewModelLoader.LoadViewModel(MvxViewModelRequest.GetDefaultRequest(typeof(MainMenuViewModel)), null, null);
}
}
}
The simplified View I want to show in the contentcontrol looks like this:
<views:MvxWpfView
x:Class="MvvmCrossTest.Wpf.Views.MainMenuView"
xmlns:views="clr-namespace:MvvmCross.Platforms.Wpf.Views;assembly=MvvmCross.Platforms.Wpf"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Background="Aqua"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
</Grid>
</views:MvxWpfView>
And also the corresponding ViewModel.
using MvvmCross.Logging;
using MvvmCross.Navigation;
using MvvmCross.ViewModels;
namespace MvvmCrossTest.Core.ViewModels
{
public class MainMenuViewModel : MvxNavigationViewModel
{
public MainMenuViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService) : base(logProvider, navigationService)
{
}
}
}
Instead of the View/ViewModel I see a text that says "MvvmCrossTest.Core.ViewModels.MainMenuViewModel".
I don't want to use Xamarin!
回答1:
I created a project where I show you some basics.
simple
You can find the samples here.
the RootView
;
<views:MvxWpfView xmlns:local="clr-namespace:SomeProject.Views" ...>
<Grid>
<Label Content="Hello from RootView" />
<local:NestedView />
</Grid>
</views:MvxWpfView>
the NestedView
;
<views:MvxWpfView ...>
<Grid>
<Label Content="Hello from NestedView" />
</Grid>
</views:MvxWpfView>
extended (custom presenter)
With this custom wpf presenter you can easily navigate to views while specified themn in a container. With that, you can close and open views from the view model while using the mvvmcross navigation service.
I copied this from another project. You can find the whole implementation in my sample project here.
the RootView
;
<views:MvxWpfView ...>
<Grid>
<Label Content="Hello" />
<ItemsControl region:MvxContainer.Id="RootViewRegion"/>
</Grid>
</views:MvxWpfView>
the RootView
code behind;
[MvxContentPagePresentation(WrapInNavigationPage = true, NoHistory = false)]
public partial class RootView: MvxWpfView<RootViewModel>
{
public RootView()
{
InitializeComponent();
}
}
the RootViewModel
;
public class RootViewModel: MvxNavigationViewModel
{
private readonly IMvxNavigationService _navigationService;
public IMvxAsyncCommand ShowNestedViewModelCommand { get; protected set; }
public RootViewModel(IMvxLogProvider logProvider, IMvxNavigationService navigationService) : base(logProvider, navigationService)
{
this._navigationService = navigationService;
// navigate to nested view
this.ShowNestedViewModelCommand = new MvxAsyncCommand(() => this._navigationService.Navigate<NestedViewModel>());
ShowNestedViewModelCommand.Execute();
}
}
the NestedView
code behind;
[MvxWpfPresenter("RootViewRegion", mvxViewPosition.NewOrExsist)]
public partial class NestedView : MvxWpfView<NestedViewModel>
{
public NestedView()
{
InitializeComponent();
}
}
good to know
when you have problems with navigation and view model connection use this code behind. It loads the viewmodel for the specific view;
[MvxContentPagePresentation(WrapInNavigationPage = true, NoHistory = false)]
public partial class SomeView : MvxWpfView<ViewModels.SomeViewModel>
{
public SomeView()
{
InitializeComponent();
if (!(ViewModel is ViewModels.SomeViewModel))
{
if (Mvx.IoCProvider.TryResolve<ViewModels.SomeViewModel>(out var someViewModel))
{
ViewModel = someViewModel;
return;
}
var _viewModelLoader = Mvx.IoCProvider.Resolve<IMvxViewModelLoader>();
var request = new MvxViewModelInstanceRequest(typeof(ViewModels.SomeViewModel));
request.ViewModelInstance = _viewModelLoader.LoadViewModel(request, null);
ViewModel = request.ViewModelInstance as ViewModels.SomeViewModel;
Mvx.IoCProvider.RegisterSingleton<ViewModels.SomeViewModel>(ViewModel);
}
}
}
回答2:
it seems that MvvmCross is wiring up Views and ViewModels automatically
I know nothing about MvvmCross, but for "automatically" to work there should be an agreement and rules, e.g. attributes or matching names (xViewModel <-> xView). Currently there is nothing I can see what connects MainMenuViewModel
with views:MvxWpfView
.
Anyway what you see
I see a text that says "MvvmCrossTest.Core.ViewModels.MainMenuViewModel"
is the view trying to visualize non-control as text due to missing data template.
It's easy to fix by just adding data template
<DataTemplate DataType="{x:Type local:MainMenuViewModel}">
<views:MvxWpfView />
</DataTemplate>
somewhere (e.g. into views:MvxWpfView.Resources
) and the view will be displayed.
来源:https://stackoverflow.com/questions/65319108/wpf-multiple-nested-usercontrols-with-mvvmcross