将Caliburn Micro Screen(UserControl)添加到WPF MVVM中的Canvas?

Kis*_*mar 1 wpf user-controls mvvm caliburn.micro

Caliburn Micro在我的项目中使用,我有许多UserControls和他们继承的viewmodel PropertyChangedBase,我希望将这个UserControl添加到我的ShellView中的Canvas.我不想使用IWindowManager显示Windows,而是希望它们在Canvas中添加.

请帮忙.我怎样才能做到这一点.

Sim*_*Fox 5

如果你ContentControl在你的内部使用,ShellView你可以挂钩到Caliburn.Micro的View-ViewModel绑定过程.

我假设ShellViewModel你有一堆暴露的属性是你的类型ViewModel.如果你ContentControl在你的位置放置一个ShellView(这可能是Canvas你想要用来布局你的Shell的容器),然后用ShellViewModel你希望它绑定的属性名称命名该控件然后,Caliburn ViewModelBinder会为你做其余的事情.

举个例子说你有一个被调用的VM FizzViewModel和一个匹配的View FizzView(它只是一个UserControl),你想要FizzView出现在你ShellView身上,你可以做类似下面的事情......

剥了一下 ShellViewModel

public class ShellViewModel : Screen, IShell
{
    public ShellViewModel(FizzViewModel theFizz)
    {
        TheFizz = theFizz;
    }

    public FizzViewModel TheFizz { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和它的匹配 ShellView

<UserControl x:Class="ANamespace.ShellView">
    <Canvas> 
        <ContentControl x:Name="TheFizz"></ContentControl>
    </Canvas> 
</UserControl>
Run Code Online (Sandbox Code Playgroud)

这里因为ContentControl名为TheFizz,它将被Caliburn绑定到你的VM上具有该名称的属性(类型之一FizzViewModel)

这样做意味着你不必沉积您UserControl使用您自己的真实类型的ShellView,你让卡利通过约定做的工作适合你(这一切就意味着它很容易更换的类型TheFizz如果你只是多添一点接口间接).

UPDATE

根据您在评论中提供的额外信息,我现在可以看到您实际上正在查看需要ItemsControl的问题.

默认的DataTemplateCaliburn使用如下所示

<DataTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
              xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro">  
    <ContentControl cal:View.Model="{Binding}"   
                    VerticalContentAlignment="Stretch"  
                    HorizontalContentAlignment="Stretch" />  
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

你会注意到它使用了a ContentControl,它具有我上面讨论过的一些优点.基本上这样做会让Caliburn为DataTemplateSelector你的物品提供类似的行为ItemsControl.因此,您可以将不同类型的VM添加到您ItemsControl绑定的集合中,此默认值DataTemplate将解析用于显示它的View类型.以下演示了一个如何实现您想要的非常简单的示例.

首先是ShellViewModel,记下BindableCollection命名的Items

[Export(typeof(IShell))]
public class ShellViewModel : IShell 
{
    public ShellViewModel()
    {
        Items = new BindableCollection<Screen>();
        _rand = new Random();
    }

    public BindableCollection<Screen> Items { get; set; }

    private Random _rand;

    public void AddItem()
    {
        var next = _rand.Next(3);
        var mPosition = System.Windows.Input.Mouse.GetPosition(App.Current.MainWindow);
        switch (next)
        {
            case 0:
                {
                    Items.Add(new BlueViewModel
                        {
                            X = mPosition.X,
                            Y = mPosition.Y,
                        });
                    break;
                }

            case 1:
                {
                    Items.Add(new RedViewModel
                    {
                        X = mPosition.X,
                        Y = mPosition.Y,
                    });
                    break;
                }
            case 2:
                {
                    Items.Add(new GreenViewModel
                    {
                        X = mPosition.X,
                        Y = mPosition.Y,
                    });
                    break;
                }
            default:
                break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后是一些要在Shell中显示的虚拟VM类型.这些可能是/你做任何你喜欢的事情:

public abstract class SquareViewModel : Screen
{
    public double X { get; set; }
    public double Y { get; set; }
}

public class BlueViewModel : SquareViewModel
{

}

public class RedViewModel : SquareViewModel
{

}

public class GreenViewModel : SquareViewModel
{

}
Run Code Online (Sandbox Code Playgroud)

现在是ShellView,请注意ItemsControl,它绑定到ShellViewModel上的Items属性

<Window x:Class="WpfApplication2.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro">

<Grid >
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>

        <ItemsControl x:Name="Items"
                      HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas cal:Message.Attach="[Event MouseLeftButtonUp] = [Action AddItem()]"
                            Background="Transparent"></Canvas>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemContainerStyle>
                <Style TargetType="ContentPresenter">
                    <Setter Property="Canvas.Left" Value="{Binding Path=X}" />
                    <Setter Property="Canvas.Top" Value="{Binding Path=Y}" />
                </Style>
            </ItemsControl.ItemContainerStyle>
        </ItemsControl>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

和的一个例子UserControl将被用于显示GreenViewModel,创建2个以上的这些,改变了名称RedViewBlueView并相应地设置背景让演示工作.

<UserControl x:Class="WpfApplication2.GreenView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Width="30"
             Height="30">
    <Grid Background="Green"></Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)

这个例子放在一起时的作用是Canvas根据鼠标点击的位置在你的shell上创建彩色方块.我认为你应该能够把它拿出来并扩展到你的需要.