Mvvm Light,UWP和代码背后

时间:2016-06-22 04:46:26

标签: c# xaml mvvm mvvm-light uwp-xaml

基于2014年Xamarin Evolve的Laurent Bugnion的this excellent presentation,我正在尝试创建我的第一个UWP / MVVM Light应用程序。

我创建了一个非常简单的文章:ObservableObject 类,其中包含2个字符串属性:RéférenceDésignation

在与文章列表视图关联的视图模型中,我有一个创建新文章的操作:

    public ArticlesViewModel(IArticleService dataService, INavigationService navigationService)
    {
        ArticleService = dataService;
        NavigationService = navigationService;

        CréeArticleCommand = new RelayCommand(CréeArticle);
    }

    public RelayCommand CréeArticleCommand { get; private set; }

    private void CréeArticle()
    {
        if (!CréeArticleCommand.CanExecute(null))
            return;

        NavigationService.NavigateTo(ViewModelLocator.ArticleDetail_Key,
                                     new ArticleViewModel(new Article(),
                                                          ArticleService,
                                                          NavigationService));
    }

这是我的文章详细信息视图的XAML:

<!-- language: xaml -->
<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UniversalTest1.UWP.Articles"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Editors="using:DevExpress.UI.Xaml.Editors"
    x:Class="UniversalTest1.UWP.Articles.Article_Detail"
    mc:Ignorable="d"
    xmlns:vm="clr-namespace:UniversalTest1.Data.ViewModels.Articles;assembly=UniversalTest1.Data"
    d:DataContext="{d:DesignInstance Type=vm:ArticleViewModel, IsDesignTimeCreatable=True}">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <TextBlock Text="Référence :"   HorizontalAlignment="Left" Margin="24,15,0,0" VerticalAlignment="Top"/>
        <TextBlock Text="Désignation :" HorizontalAlignment="Left" Margin="10,52,0,0" VerticalAlignment="Top"/>

        <Editors:TextEdit Text="{Binding Article.Référence, Mode=TwoWay}" HorizontalAlignment="Left" Margin="100,8,0,0" VerticalAlignment="Top" Width="300"/>
        <Editors:TextEdit Text="{Binding Article.Désignation, Mode=TwoWay}" HorizontalAlignment="Left" Margin="100,45,0,0" VerticalAlignment="Top" Width="500"/>

        <Button Content="Sauver" Command="{Binding SauverCommand}" HorizontalAlignment="Left" Margin="102,84,0,0" VerticalAlignment="Top"/>
    </Grid>
</Page>

我的问题是我必须在我的页面后面的代码中定义DataContext:

public sealed partial class Article_Detail : Page
{
    public Article_Detail()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        DataContext = (ArticleViewModel)e.Parameter;
    }
}

有没有办法让设计时间DataContext保持在Xaml页面的d:DataContext部分中定义,并且在运行时,从Navigation参数中获取DataContext?

我的目标是让代码背后的代码更少。所以我想在XAML中定义运行时DataContext。

2 个答案:

答案 0 :(得分:1)

您可以使用依赖项注入为viewmodel创建设计或运行时服务实例。使用视图模型定位器,您可以执行以下操作:

public class ViewModelLocator
{
    static ViewModelLocator()
    {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);

        if (ViewModelBase.IsInDesignModeStatic)
        {
            if (!SimpleIoc.Default.IsRegistered<IArticleService>())
            {
                SimpleIoc.Default.Register<IArticleService, DesignArticleService>();
            }
        }
        else
        {
            if (!SimpleIoc.Default.IsRegistered<IArticleService>())
            {
                SimpleIoc.Default.Register<IArticleService, ArticleService>();
            }
        }

        SimpleIoc.Default.Register<ArticleViewModel>();
    }

    public ArticleViewModel ArticleViewModel => ServiceLocator.Current.GetInstance<ArticleViewModel>();
}

在App.xaml中注册定位器

<Application
    x:Class="UniversalTest1.App" // your namespace
    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" 
    mc:Ignorable="d" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:viewModel="using:UniversalTest1.Data.ViewModels"> // your namespace

    <Application.Resources>

        <ResourceDictionary>
            <viewModel:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
        </ResourceDictionary>

    </Application.Resources>

</Application>

然后你可以在你的xaml中引用它:

<Page
...
DataContext="{Binding ArticleViewModel, Source={StaticResource Locator}}">

您还可以在此处查看示例代码https://mvvmlight.codeplex.com/SourceControl/latest#Samples/Flowers/Flowers.Data/ViewModel/ViewModelLocator.cs

答案 1 :(得分:0)

为此,您需要使用自己的NavigationService实现。这个概念是导航到您的页面并同时调用 ViewModel 来处理参数并设置 DataContext

以下是此模式的两个示例: