向网格 MVVM Caliburn 添加更多用户控件

我正在建造一个驾驶舱,我有很多用户控制(不同类型的开关),我试图将它们集成到一个窗口中


我正在使用 caliburn 和 Ninject 并尝试保留 MVVM。


所以我有一个问题,我必须将不同的开关动态集成到窗口的网格中,我不知道我是否可以保留 MVVM


所以在我的解决方案中,我使用网格的名称将不同的用户控件放置在不同的位置,并且我打破了 MVVM


我怎么能用 MVVM 做到这一点?我读过我可以使用 ContentControl 从列表中绑定不同的 ViewModel,但我不知道该怎么做。欢迎提供帮助


引导程序.cs:


using Caliburn.Micro;

using Ninject;

using System;

using System.Collections.Generic;

using System.Windows;

using System.Windows.Input;

using TestNinjectCaliburn.ViewModels;

using EventAggregator = TestNinjectCaliburn.Events.EventAggregator;

using IEventAggregator = TestNinjectCaliburn.Events.IEventAggregator;


namespace TestNinjectCaliburn

{

    public class Bootstrapper : BootstrapperBase

    {

        private IKernel kernel;

        public Bootstrapper()

        {

            Initialize();

        }


        protected override void Configure()

        {

            kernel = new StandardKernel();


            kernel.Bind<IEventAggregator>().To<EventAggregator>().InSingletonScope();

            kernel.Bind<IWindowManager>().To<WindowManager>().InSingletonScope();

            kernel.Bind<MainWindowViewModel>().ToSelf().InSingletonScope();


            MessageBinder.SpecialValues.Add("$pressedkey", (context) =>

            {

                // NOTE: IMPORTANT - you MUST add the dictionary key as lowercase as CM

                // does a ToLower on the param string you add in the action message, in fact ideally

                // all your param messages should be lowercase just in case. I don't really like this

                // behaviour but that's how it is!

                var keyArgs = context.EventArgs as KeyEventArgs;


                if (keyArgs != null)

                    return keyArgs.Key;


                return null;

            });

        }



GCT1015
浏览 72回答 1
1回答

杨魅力

网格是这里使用的错误面板。如果您正在设计驾驶舱,那么您已经知道元素的位置,因此您不需要 WPF 来为您进行布局。因此,使用 Canvas。您可能希望您的驾驶舱随视图缩放,因此根据您自己选择的任意单位(例如 1000x1000)为其指定一个大小,并将整个内容包装在一个 Viewbox 中。关于元素的实际呈现,您在屏幕上呈现控件列表,每当您这样做时,您的第一直觉应该是使用 ItemsControl。因此,您将从驾驶舱元素的某种类型的基本视图模型开始,然后将它们全部放在一个列表中。要显示它们,您可以使用 ItemsControl,将 ItemsSource 绑定到您的列表。您希望在 Canvas 上显示所有控件,因此模板化 ItemControl 的 ItemsPanel。最后,您需要指定每个元素在屏幕上的位置,因此为您的基本视图模型类提供 X/Y 属性并绑定到 ItemControl 的 ItemContainerStyle 中的那些。把所有这些放在一起,你会得到这个:<Viewbox>&nbsp; &nbsp; <ItemsControl ItemsSource="{Binding MyCockpitViewModels}" Width="1000" Height="1000">&nbsp; &nbsp; &nbsp; &nbsp; <!-- Replace panel with a canvas -->&nbsp; &nbsp; &nbsp; &nbsp; <ItemsControl.ItemsPanel>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Canvas />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </ItemsPanelTemplate>&nbsp; &nbsp; &nbsp; &nbsp; </ItemsControl.ItemsPanel>&nbsp; &nbsp; &nbsp; &nbsp; <!-- Set position of each element in the canvas -->&nbsp; &nbsp; &nbsp; &nbsp; <ItemsControl.ItemContainerStyle>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Style TargetType="{x:Type ContentPresenter}">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Setter Property="Canvas.Left" Value="{Binding X}" />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Setter Property="Canvas.Top" Value="{Binding Y}" />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </Style>&nbsp; &nbsp; &nbsp; &nbsp; </ItemsControl.ItemContainerStyle>&nbsp; &nbsp; </ItemsControl></Viewbox>如果你运行它,你会看到视图模型的名称显示在它们各自的画布位置,所以剩下要做的唯一一件事就是以某种方式告诉 WPF 要为每个元素而不是文本绘制哪些控件。这是通过 DataTemplates 完成的,您可以将其放置在可视树中的任何位置,例如 app.xaml 的 ResourceDictionary,或者用于 MainWindow 的那个,或者更好的是放在 ItemsControl 的资源块中:<DataTemplate DataType="{vm:SwitchOffOn_ViewModel}">&nbsp; &nbsp; <controls:SwitchOffOn_View /></DataTemplate>自从我使用 Micro 以来已经有一段时间了,它实际上可能会为您执行此 DataTemplating,但如果没有,请按照我在此处为您的每个控件显示的那样明确声明它,您将拥有一个完全呈现的驾驶舱。
打开App,查看更多内容
随时随地看视频慕课网APP