【问题标题】:WTS Cannot declare ViewModelLocator in XAMLWTS 无法在 XAML 中声明 ViewModelLocator
【发布时间】:2019-03-26 13:01:51
【问题描述】:

我已经使用 Windows Template Studio 创建了我的 MVVM Light 应用程序,现在我正在尝试在我的 XAML 中使用数据绑定。但这对我来说似乎不可能使用生成的代码,因为它没有在 XAML 中声明 Viewmodel。我更改了代码来执行此操作,但后来我偶然发现了这个错误:

无法构造 XAML ViewModelLocator 类型。为了在 XAML 中构造,类型不能是抽象、接口、嵌套、泛型或结构,并且必须具有公共默认构造函数

我尝试将构造函数公开,但这并不能解决问题。关于如何让数据绑定工作的任何想法?

这是所有代码:

App.XAML

<Application
x:Class="PatientApp.UWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:PatientApp.UWP.ViewModels">

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <XamlControlsResources  xmlns="using:Microsoft.UI.Xaml.Controls"/>
            <ResourceDictionary Source="/Styles/_Colors.xaml"/>
            <ResourceDictionary Source="/Styles/_FontSizes.xaml"/>
            <ResourceDictionary Source="/Styles/_Thickness.xaml"/>
            <ResourceDictionary Source="/Styles/TextBlock.xaml"/>
            <ResourceDictionary Source="/Styles/Page.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <vm:ViewModelLocator xmlns:vm="using:PatientApp.UWP.ViewModels" x:Key="Locator" />
    </ResourceDictionary>
</Application.Resources>

ViewModelLocator:

    [Windows.UI.Xaml.Data.Bindable]
public class ViewModelLocator
{
    private static ViewModelLocator _current;

    public static ViewModelLocator Current => _current ?? (_current = new ViewModelLocator());

    private ViewModelLocator()
    {
        SimpleIoc.Default.Register(() => new NavigationServiceEx());
        SimpleIoc.Default.Register<ShellViewModel>();
        Register<PatientsViewModel, AllPatientsPage>();
        Register<DiseasesViewModel, AllDiseasesPage>();
    }

    public DiseasesViewModel DiseasesViewModel => SimpleIoc.Default.GetInstance<DiseasesViewModel>();

    public PatientsViewModel PatientsViewModel => SimpleIoc.Default.GetInstance<PatientsViewModel>();

    public ShellViewModel ShellViewModel => SimpleIoc.Default.GetInstance<ShellViewModel>();

    public NavigationServiceEx NavigationService => SimpleIoc.Default.GetInstance<NavigationServiceEx>();

    public void Register<VM, V>()
        where VM : class
    {
        SimpleIoc.Default.Register<VM>();

        NavigationService.Configure(typeof(VM).FullName, typeof(V));
    }
}

患者页面:

<Page
x:Class="PatientApp.UWP.Views.AllPatientsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Style="{StaticResource PageStyle}"
mc:Ignorable="d"
xmlns:datamodel="using:PatientApp.Model"
DataContext="{Binding PatientViewModelInstance, Source={StaticResource Locator}}">
<Grid
        Background="{ThemeResource SystemControlPageBackgroundChromeLowBrush}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <CommandBar DefaultLabelPosition="Right"
                Grid.Row="0"
                OverflowButtonVisibility="Collapsed">

        <AppBarButton Icon="Sort" Label="Sort" />
        <AppBarButton Icon="Edit" Label="Edit" />
        <AppBarButton Icon="Add" Label="Add" />
        <AppBarButton Icon="Zoom" Label="Search" />
    </CommandBar>
    <GridView  x:Name="Patients"
               Grid.Row="1"
               ItemsSource="{Binding Patients}">
        <GridView.ItemsPanel>
            <ItemsPanelTemplate>
                <ItemsStackPanel Margin="14,0,0,0" Orientation="Vertical" />
            </ItemsPanelTemplate>
        </GridView.ItemsPanel>
        <GridView.ItemTemplate>
            <DataTemplate x:DataType="datamodel:Patient">
                <TextBlock Text="{x:Bind Name}"
                                   FontWeight="Medium"
                                   TextWrapping="NoWrap"
                                   HorizontalAlignment="Left" />
            </DataTemplate>
        </GridView.ItemTemplate>
    </GridView>
</Grid>

【问题讨论】:

    标签: mvvm uwp


    【解决方案1】:

    无法构造 XAML ViewModelLocator 类型。为了在 XAML 中构造,类型不能是抽象、接口、嵌套、泛型或结构,并且必须具有公共默认构造函数

    原因是ViewModelLocator 构造方法在您的场景中是私有的。所以你不能在 xaml 中实例化它。您可以将其更改为公开。即使你不能使用它。因为 xaml 中的 ViewModelLocator 实例是由构造函数而不是单例方法创建的。换句话说,&lt;vm:ViewModelLocator xmlns:vm="using:PatientApp.UWP.ViewModels" x:Key="Locator" /&gt; 不等于 ViewModelLocator.Current。不幸的是,ActivationService 使用了ViewModelLocator.Current 来获得NavigationService。所以应用启动时会抛出异常。

    public static NavigationServiceEx NavigationService => ViewModelLocator.Current.NavigationService;
    

    很难用 MVVMLight 接近。通常,页面 DataContext 在后面的代码中进行了保护。并用 x:bind 绑定数据源。

    private SettingsViewModel ViewModel
    {
        get { return ViewModelLocator.Current.SettingsViewModel; }
    }
    

    【讨论】:

    • 确实!使用 {x:Bind ViewModel.Patients} 似乎可以像我想要的那样工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多