为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
GCT1015 2022-12-31 13:20:11
我正在建造一个驾驶舱,我有很多用户控制(不同类型的开关),我试图将它们集成到一个窗口中我正在使用 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;            });        }
查看完整描述

1 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

网格是这里使用的错误面板。如果您正在设计驾驶舱,那么您已经知道元素的位置,因此您不需要 WPF 来为您进行布局。因此,使用 Canvas。您可能希望您的驾驶舱随视图缩放,因此根据您自己选择的任意单位(例如 1000x1000)为其指定一个大小,并将整个内容包装在一个 Viewbox 中。


关于元素的实际呈现,您在屏幕上呈现控件列表,每当您这样做时,您的第一直觉应该是使用 ItemsControl。因此,您将从驾驶舱元素的某种类型的基本视图模型开始,然后将它们全部放在一个列表中。要显示它们,您可以使用 ItemsControl,将 ItemsSource 绑定到您的列表。您希望在 Canvas 上显示所有控件,因此模板化 ItemControl 的 ItemsPanel。最后,您需要指定每个元素在屏幕上的位置,因此为您的基本视图模型类提供 X/Y 属性并绑定到 ItemControl 的 ItemContainerStyle 中的那些。把所有这些放在一起,你会得到这个:


<Viewbox>

    <ItemsControl ItemsSource="{Binding MyCockpitViewModels}" Width="1000" Height="1000">


        <!-- Replace panel with a canvas -->

        <ItemsControl.ItemsPanel>

            <ItemsPanelTemplate>

                <Canvas />

            </ItemsPanelTemplate>

        </ItemsControl.ItemsPanel>


        <!-- Set position of each element in the canvas -->

        <ItemsControl.ItemContainerStyle>

            <Style TargetType="{x:Type ContentPresenter}">

                <Setter Property="Canvas.Left" Value="{Binding X}" />

                <Setter Property="Canvas.Top" Value="{Binding Y}" />

            </Style>

        </ItemsControl.ItemContainerStyle>


    </ItemsControl>

</Viewbox>

如果你运行它,你会看到视图模型的名称显示在它们各自的画布位置,所以剩下要做的唯一一件事就是以某种方式告诉 WPF 要为每个元素而不是文本绘制哪些控件。这是通过 DataTemplates 完成的,您可以将其放置在可视树中的任何位置,例如 app.xaml 的 ResourceDictionary,或者用于 MainWindow 的那个,或者更好的是放在 ItemsControl 的资源块中:


<DataTemplate DataType="{vm:SwitchOffOn_ViewModel}">

    <controls:SwitchOffOn_View />

</DataTemplate>

自从我使用 Micro 以来已经有一段时间了,它实际上可能会为您执行此 DataTemplating,但如果没有,请按照我在此处为您的每个控件显示的那样明确声明它,您将拥有一个完全呈现的驾驶舱。


查看完整回答
反对 回复 2022-12-31
  • 1 回答
  • 0 关注
  • 71 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信