【问题标题】:How to load content properly inside a ModernWindow using mvvm如何使用 mvvm 在 ModernWindow 中正确加载内容
【发布时间】:2016-07-24 14:45:44
【问题描述】:

在我们公司,我们习惯于使用 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. 创建引导程序类

    
    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 & 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");
        }
    }
    

我的问题是,第 6 步,为什么函数什么都不做?如果我的方法错了,有人可以指导我找到更好的方法吗?

如果这是最好的方法,我如何从 ClickMe 函数导航到另一个视图。

【问题讨论】:

  • 我意识到这不是您寻求的答案,但现实是直接从 Winforms 跳转到 Caliburn.Micro + MUI + MVVM,这是一个非常糟糕的主意。您应该先独立学习它们中的每一个,然后再尝试整合。它们很难理解(即使它们看起来不像),当您将所有未知数放在一个大熔炉中时,它们就是一场噩梦。

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


【解决方案1】:

至于你的第一个问题,为什么函数什么都不做,我认为这可能与你项目的层次结构有关。使用 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:Link 标记中的 source 属性指向我的主窗口到我的 settingsPage.xaml 文件的实际路径。然后,MUI 将在内容提供程序中加载并显示该路径,该路径由 MUI ModernWindow 类默认样式模板为您放置在您的主窗口中。您无需额外的代码即可导航(直到您需要复杂的子视图导航)。

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

Mui 源代码可以在 GitHub 上的 Mui GithubLink 找到。在这里你可以下载示例程序,谁的代码在appLink here for covience下的同一个仓库中找到。

我对 Caliburn.Micro 不熟悉,所以我不确定两者如何集成在一起,例如 Caliburn.Micro 的功能要求。我确实知道 MUI 如何与 MVVM light 集成,并且在我之前的研究中,我在互联网上找到了很多这样的示例。

【讨论】:

    猜你喜欢
    • 2021-08-04
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    相关资源
    最近更新 更多