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

时间:2012-05-07 12:16:23

标签: wpf mvvm user-controls caliburn.micro

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

请帮忙。我怎么能这样做。

1 个答案:

答案 0 :(得分:5)

如果您在ContentControl中使用ShellView,则可以挂钩到Caliburn.Micro的View-ViewModel绑定过程。

我认为在你的ShellViewModel中,你有一堆属性ViewModel。如果您在ContentControl中放置ShellView(如果这是您希望用来布置Shell的容器,则可能是Canvas的孩子),然后将其命名为控制你希望它绑定到的ShellViewModel中的属性名称,然后Caliburn的ViewModelBinder将为你完成其余的工作。

例如,假设您有一个名为FizzViewModel的VM和一个名为FizzView的匹配视图(只是UserControl),您希望FizzView出现在您的ShellView您可以执行以下操作...

剥离后退ShellViewModel

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

    public FizzViewModel TheFizz { get; set; }
}

及其匹配ShellView

<UserControl x:Class="ANamespace.ShellView">
    <Canvas> 
        <ContentControl x:Name="TheFizz"></ContentControl>
    </Canvas> 
</UserControl>

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

这样做意味着您不必在UserControl上使用他们的真实类型来放置您的ShellView,您让Caliburn通过约定为您完成工作(这一切都意味着它很容易如果只是添加一点接口间接,则换掉类型TheFizz。

更新

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

默认DataTemplate Caliburn使用如下所示

<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>

你会注意到它使用的是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;
        }
    }
}

然后在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
{

}

现在是一个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>

用于显示UserControl的{​​{1}}示例,再创建2个,将名称更改为GreenViewModelRedView并设置适当的背景使演示工作。

BlueView

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