Caliburn Micro,如何使用ViewModel First使用ContentControl(或显示'sub'ViewModel)

时间:2016-06-01 08:32:51

标签: c# wpf mvvm caliburn.micro

我首先使用ViewModel在我的应用程序中使用MVVM框架Caliburn Micro(或者我认为)。但是,当我使用TryClose(true)无法关闭它的父窗口的对话框出现问题时,偶然发现了这个完全概述我的问题的问题,我也得到了“TryClose需要父IConductor或带有关闭的视图方法或IsOpen属性。“:

Caliburn.Micro - ShowDialog() how to close the dialog?

但是,我不确定如何实施解决方案。答案说明:

  

删除cal:Bind.Model和cal:View.Model绑定...

原来使用这些绑定是View-First方法,我不知道我在做什么。以下是我的违规对话示例:

<UserControl ... Height="206" Width="415">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="AUTO" />
        </Grid.RowDefinitions>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Button x:Name="Okay" Content="Okay" Width="100" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" />
            <Button x:Name="Cancel" Content="Cancel" Width="100" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" />
        </Grid>
        <ContentControl cal:View.Model="{Binding TimeSpanViewModel}"/>
    </Grid>
</UserControl>

它只是一个包含一个已经存在的ViewModel的ok和取消按钮的包装器(谁的视图由caliburn解析,因此我认为我首先在做ViewModel)。如果我删除了这个cal:View.Model绑定,我确实恢复了关闭对话框的能力,但是我放弃了所有实际内容。我正在使用ContentControl在我的应用程序中显示内容(在ItemsControls,对话框,弹出窗口等中)。

我的问题是,应该我是如何在ViewModel首次Caliburn中显示ViewModel的?

编辑:我正在使用WindowManager显示DialogViewModel(继承屏幕),如下所示:

[Export(typeof(IWindowManager))]
public class AppWindowManager : MetroWindowManager, IDialogManager
{
    AppViewModel Content { get; set; }

    public AppWindowManager()
    {

    }

    public override MetroWindow CreateCustomWindow(object view, bool windowIsView)
    {
        if (windowIsView)
        {
            return view as MainWindowContainer;
        }

        MainWindowContainer window = new MainWindowContainer();
        //{
        window.Content = view;
        //};

        return window;
    }

    public override bool? ShowDialog(object rootModel, object context = null, IDictionary<string, object> settings = null)
    {
        Window window = CreateWindow(rootModel, true, context, settings);

        return window.ShowDialog();
    }

    public object ShowCustomDialog(object rootModel, string title, bool showWindowsOptions = true)
    {
        dynamic settings = new ExpandoObject();
        settings.Title = title;
        settings.ShowCloseButton = showWindowsOptions;
        settings.ShowMaxRestoreButton = showWindowsOptions;
        settings.ShowMinButton = showWindowsOptions;
        settings.SizeToContent = SizeToContent.WidthAndHeight;
        return ShowDialog(rootModel, null, settings);
    }

    public ILoadingDialogViewModel CreateLoadingDialogManager()
    {
        return new LoadingDialogViewModel(this);
    }
}

2 个答案:

答案 0 :(得分:3)

回答主要问题

  

我应该如何在ViewModel首次Caliburn中显示ViewModel?

我认为select t1.ID from Table1 as t1 left join Table2 as t2 on t1.ID=t2.ID where t2.ID is null and t2.MessageType<>'Request Received' 是您在ViewModel上拥有TimeSpanViewModel(并且ViewModel正在导出自身)的属性?我认为您应该将[Import]更改为cal:View.Model="{Binding TimeSpanViewModel}"。即使这可能无法解决问题,也是正确的做法,Caliburn将确保它正确绑定。

我试图重现你的问题,但即使用你的方式它也适合我。那么为什么它不能像你现在这样做,这是一个很好的(第二个)问题。

最大的问题可能是你的AppWindowManager,如果你在那里创建的窗口没有通过正确的Caliburn代码,它将无法正确绑定。由于缺少很多代码,我甚至不确定x:Name="TimeSpanViewModel"在那里做了什么,大多数我可以推测。您是否尝试使用默认的WindowManager实现,只是为了查看它是否适用于它?

答案 1 :(得分:1)

对于Caliburn.Micro新手并且与此线程相关的人,如果在AppBootStrapper中使用Caliburn.Micro的SimpleContainer作为IoC依赖注入容器,那么就不要使用MEF或任何其他IoC容器实现。

许多旧的StackOverflow讨论和代码在Internet上使用MEF和Caliburn.Micro,但Caliburn.Micro提供的SimpleContainer可能足以满足您的项目(如果是这样,请不要让MEF代码混淆你看例子。)

Calburn.Micro Wiki entry for SimpleContainer.