如何使用mvvm在ModernWindow中正确加载内容

时间:2016-04-04 21:25:42

标签: c# wpf mvvm caliburn.micro modern-ui

在我们公司,我们习惯使用WinForms开发我们的应用程序, 现在我们决定使用Caliburn.Micro和Modern UI切换到WPF-MVVM。 我们试图达到的目标是拥有一个小应用程序: - 1个现代窗户 - 现代窗口内的2页 目标是在该页面内有一个按钮,用于将现代窗口导航到带参数的第二页。

我一直在努力了解如何解决这个问题,我成功地使用了Window(没有MUI),但是当涉及MUI时,它并没有真正给我我想要的结果

到目前为止,我所做的一切都是

  1. 创建新的MUI项目
  2. 将Caliburn.Micro添加到项目
  3. 将App.xaml更改为

    <Application x:Class="MuiWithCaliburn01.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:MuiWithCaliburn01">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:AppBootstrapper x:Key="bootstrapper" />
                    <local:ModernContentLoader x:Key="ModernContentLoader" />
                </ResourceDictionary>
                <ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.xaml" />
                <ResourceDictionary Source="/FirstFloor.ModernUI;component/Assets/ModernUI.Light.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
    

  4. 创建Bootstrapper类

    
    public class AppBootstrapper : BootstrapperBase
    {
        static AppBootstrapper()
        {
        }
        public AppBootstrapper()
        {
            Initialize();
        }
        protected override void OnStartup(object sender, StartupEventArgs e)
        {
            DisplayRootViewFor();
        }
    }
    
  5. 创建ModernContentLoader类

    
    public class ModernContentLoader : DefaultContentLoader
    {
        protected override object LoadContent(Uri uri)
        {
            var content = base.LoadContent(uri);
            if (content == null)
                return null;
            var vm = Caliburn.Micro.ViewModelLocator.LocateForView(content);
            if (vm == null)
                return content;
            if (content is DependencyObject)
            {
                Caliburn.Micro.ViewModelBinder.Bind(vm, content as DependencyObject, null);
            }
            return content;
        }
    }
    
  6. ModernWindowView.xaml&amp; ModernWindowViewModel.cs

    
    < mui:ModernWindow x:Class="MuiWithCaliburn01.ModernWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:mui="http://firstfloorsoftware.com/ModernUI"
        ContentLoader="{StaticResource ModernContentLoader}">
    < mui:ModernWindow.MenuLinkGroups>
        < mui:LinkGroupCollection>
            < mui:LinkGroup DisplayName="Hello">
                < mui:LinkGroup.Links>
                    < mui:Link Source="Child1View.xaml" DisplayName="Click me">< /mui:Link>
                < /mui:LinkGroup.Links>
            < /mui:LinkGroup>
        < /mui:LinkGroupCollection>
    < /mui:ModernWindow.MenuLinkGroups>
    < /mui:ModernWindow>
    

    class ModernWindowViewModel : Conductor.Collection.OneActive
    {
        public ModernWindowViewModel()
        {
            //this function is doing nothing in the ModernWindow, but it works great in the Window.
            ActivateItem(new Child1ViewModel());
        }
    }
    

  7. 最后,Child1View.xaml

    <UserControl x:Class="MuiWithCaliburn01.Child1View"
        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" 
        xmlns:mui="http://firstfloorsoftware.com/ModernUI"
        mc:Ignorable="d" 
        xmlns:cal="http://www.caliburnproject.org"
        xmlns:model="clr-namespace:MuiWithCaliburn01"
        d:DataContext="{x:Type model:Child1ViewModel}"
        d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
            <Button cal:Message.Attach="ClickMe" Width="140" Height="50">Hello World</Button>
        </Grid>
    </UserControl>
    

    和Child1ViewModel.cs

    public class Child1ViewModel : Conductor<IScreen>
    {
        public void ClickMe()
        {
            MessageBox.Show("Hello");
        }
    }
    
  8. 我的问题是,第6步,为什么函数什么都不做?如果我的方式有问题,任何人都可以指导我更好的方式吗?

    如果它是最佳方法,我如何从ClickMe功能导航到另一个视图。

1 个答案:

答案 0 :(得分:5)

关于你为什么什么都不做的第一个问题,我认为它可能与你的项目的层次结构有关。使用MUI,这是我的一个应用程序的主要(也是唯一)窗口

<mui:ModernWindow x:Class="namespace.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mui="http://firstfloorsoftware.com/ModernUI"
    Title="Window Title" IsTitleVisible="True"
    ContentSource="/Pages/Home.xaml"
    Style="{StaticResource MyModernWindow}">

<mui:ModernWindow.TitleLinks>
    <mui:Link DisplayName="settings" Source="/Pages/SettingsPage.xaml" />
</mui:ModernWindow.TitleLinks>

在我的项目层次结构中,我有我的项目根目录(CSPROJ文件),MainWindow.xaml然后是Pages文件夹。在我的页面文件夹中,我有我的SettingsPage.xaml。我的mui中的source属性:Link标记指向我的主窗口到settingsPage.xaml文件的实际路径。然后,MUI将通过MUI ModernWindow类默认样式模板加载并显示在您的主窗口中放置的内容提供程序中的该路径。您无需额外的代码进行导航(直到您需要复杂的子视图导航)。

我的settingsPage.xaml文件是一个普通的用户控件,网格的样式分配给ContentRoot静态资源样式,因为它还包含其他视图/页面。

Mui来源可以在Mui GithubLink的GitHub上找到。在这里,您可以下载示例程序,其代码位于app Link here for covience下的同一存储库中。

我不熟悉Caliburn.Micro,所以我不确定这两者是如何集成在一起的,例如Caliburn.Micro的要求。我知道MUI如何与MVVM光集成,并且我手头的研究中有很多这样的例子。