Caliburn.Micro实现设计时预览

发布时间 2023-05-23 16:35:11作者: euv

Design Time :设计时
Running Time : 运行时

Caliburn.Micro 使用名称约定为ViewModel自动寻找View,所以不能像CommunityToolkit.Mvvm那样,在View中以XAML形式显示指定DataContext对应的ViewModel,从而可以在设计器模式预览使用Mock数据呈现的View的效果,或者对XAML形式的Binding语句中的源属性名称字符串按F12键直接跳转到ViewModel。

其实,非也。Visual Studio的XAML设计器支持设置View在设计器模式的宽高和DataContext,可以让我们不需要启动程序便能观察到待模拟数据的View的效果以及F12跳转到ViewModel,神奇的是,当我们真正启动程序后看到的View使用的是真实数据而不是模拟数据。

两个命名空间
设计时特性
  • d:DesignHeight | 在设计器中看到的高度,程序启动后看到的实际高度是Height
  • d:DesignWidth | 在设计器中看到的宽度,程序启动后看到的实际高度是Width
  • d:DataContext="{d:DesignInstance Type=local:MainViewModel,IsDesignTimeCreatable=True}" | 在设计器中使用的ViewModel,,程序启动后使用的ViewModel是Caliburn.Micro根据名称约定规则找到的ViewModel。值得一提的是,ViewModel必须有无参构造函数才可For this to work, the ViewModel must have a default constructor. If this isn’t suitable, you can also use a ViewModelLocator for your design-time ViewModel creation.
  • cm:Bind.AtDesignTime="True" | 这个必须加上去,这样if(IsInDesignMode) {......}就不是必须写在ViewModel的构造方法中才能在设计器中看到模拟数据的展现效果,简而言之,加上去,能够增强设计时设计器显示模拟数据的能力!
实际案例

View

<Window
    x:Class="设计器模式.MainView"
    xmlns:cm="http://caliburnmicro.com"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="MainView"
    Width="800"
    Height="450"
    cm:Bind.AtDesignTime="True"
    d:DataContext="{d:DesignInstance Type=local:MainViewModel,
                                     IsDesignTimeCreatable=True}"
    d:DesignHeight="200"
    d:DesignWidth="200"
    mc:Ignorable="d">
</Window>

ViewModel

internal class MainViewModel : Screen
{
    private readonly IWindowManager _WindowManager;

    private bool IsInDesignMode
    {
        get => (bool)DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue;
    }

    public MainViewModel(IWindowManager windowManager)
    {
        _WindowManager = windowManager;
    }

    public MainViewModel()
    {
        _WindowManager = IoC.Get<IWindowManager>();
    }

    protected override void OnViewLoaded(object view)
    {
        if (IsInDesignMode)
        {
            Info = "Designed Mode";
        }
        else
        {
            Info = "Running Time";
        }
        
        NotifyOfPropertyChange(nameof(Info));
        base.OnViewLoaded(view);
    }

    public string Info { get; set; }
}