结合MahApps.Metro和Caliburn.Micro

14

我试图将MahApps.Metro和Caliburn.Micro一起使用,但遇到了一些问题。

这是我的启动器

public sealed class TestBootstrapper : Bootstrapper<ShellViewModel> 
{
    private CompositionContainer container;

    protected override void Configure()
    {
        container = new CompositionContainer(new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()));

        CompositionBatch batch = new CompositionBatch();

        batch.AddExportedValue<IWindowManager>(new AppWindowManager());
        batch.AddExportedValue<IEventAggregator>(new EventAggregator());
        batch.AddExportedValue(container);

        container.Compose(batch);
    }

    protected override object GetInstance(Type serviceType, string key)
    {
        string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
        var exports = container.GetExportedValues<object>(contract);

        if (exports.Count() > 0)
        {
            return exports.First();
        }

        return base.GetInstance(serviceType, key);
    }
}

这里是我的AppWindowManager。

public sealed class AppWindowManager : WindowManager
{
    static readonly ResourceDictionary[] resources;
    static AppWindowManager()
    {
        resources = new ResourceDictionary[] 
        {
            new ResourceDictionary
            { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml", UriKind.RelativeOrAbsolute) },
            new ResourceDictionary
            { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml", UriKind.RelativeOrAbsolute) },
            new ResourceDictionary
            { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml", UriKind.RelativeOrAbsolute) },
            new ResourceDictionary
            { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml", UriKind.RelativeOrAbsolute) },
            new ResourceDictionary
            { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml", UriKind.RelativeOrAbsolute) },
            new ResourceDictionary
            { Source = new Uri("pack://application:,,,/MahApps.Metro;component/Styles/Controls.AnimatedTabControl.xaml", UriKind.RelativeOrAbsolute) }
        };
    }

    protected override Window EnsureWindow(object model, object view, bool isDialog)
    {
        MetroWindow window = view as MetroWindow;
        if (window == null)
        {
            window = new MetroWindow()
            {
                Content = view,
                SizeToContent = SizeToContent.WidthAndHeight
            };
            window.MinHeight = 150;
            window.MinWidth = 500;
            foreach (ResourceDictionary resourceDictionary in resources)
            {
                window.Resources.MergedDictionaries.Add(resourceDictionary);
            }
            window.SetValue(View.IsGeneratedProperty, true);
            Window owner = this.InferOwnerOf(window);
            if (owner != null)
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
                window.Owner = owner;
            }
            else
            {
                window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
            }
        }
        else
        {
            Window owner2 = this.InferOwnerOf(window);
            if (owner2 != null && isDialog)
            {
                window.Owner = owner2;
            }
        }
        return window;
    }
}

这个方法有些有效,但是窗口周围会有一个黑色的边框,直到我调整大小才消失,如下所示: enter image description here

为什么会有黑色边框,我该如何去除它(如果我手动调整窗口大小,边框就会消失)?


1
谢谢您发布这篇文章,您上面的代码为我节省了不少时间! - Kelly
https://github.com/ziyasal/Caliburn.Metro - CAD bloke
3个回答

10

使用 Caliburn.Micro 2 和 Mahapps.Metro 1,以上两个框架的组合已不再有效。

在查阅了 Caliburn.Micro 文档并按照过时的指南进行了一些挖掘后,我得出了以下结论。

首先创建启动引导程序,如下所示:

public class AppBootstrapper : BootstrapperBase
{
    private CompositionContainer container;

    public AppBootstrapper()
    {
        Initialize();
    }

    protected override void Configure() 
    {
        container = new CompositionContainer(
            new AggregateCatalog(
                AssemblySource.Instance.Select(
                x => new AssemblyCatalog(x)).OfType<ComposablePartCatalog>()
                )
            );

        CompositionBatch batch = new CompositionBatch();

        batch.AddExportedValue<IWindowManager>(new WindowManager());
        batch.AddExportedValue<IEventAggregator>(new EventAggregator());
        batch.AddExportedValue(container);

        container.Compose(batch);

    }

    protected override object GetInstance(Type service, string key) 
    {
        string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(service) : key;
        var exports = container.GetExportedValues<object>(contract);

        if(exports.Any())
        {
            return exports.First();
        }

        throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
    }

    protected override IEnumerable<object> GetAllInstances(Type service)
    {
        return container.GetExportedValues<object>(AttributedModelServices.GetContractName(service));
    }

    protected override void BuildUp(object instance) 
    {
        container.SatisfyImportsOnce(instance);
    }

    protected override void OnStartup(object sender, StartupEventArgs e) 
    {
        DisplayRootViewFor<IShell>();
    }
}

接下来,将引导程序和 MahApps.Metro 资源添加到 App.xaml 文件中,像这样:

<Application x:Class="your-namespace.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:your-namespace">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:AppBootstrapper x:Key="bootstrapper" />
                </ResourceDictionary>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

接下来的步骤是确保您的ShellViewModel具有正确的导出项(这是设置mef启动器的简单要求,不要忘记创建IShell类(因为它是标准的,在此不予展示)),代码如下:

[Export(typeof(IShell))]
public class ShellViewModel : PropertyChangedBase, IShell 
{

}

最后但同样重要的是,我们需要设置ShellView以使用MahApps.Metro窗口:

<Controls:MetroWindow x:Class="your-namespace.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro">

    <Grid Background="White">
        <TextBlock Text="Hello Caliburn Micro!"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"
                   FontSize="20" />
    </Grid>

</Controls:MetroWindow>

希望这可以帮助其他想要在最新版本中结合Caliburn.Micro和MahApps.Metro的人。


如果有人能够验证这是否是正确的解决方案,那么我会将其标记为答案! - Peter
Phil,谢谢你发布这个内容,我使用最新版本的Caliburn和Mahapps Metro得到了它的工作。 - Patrick Allwood
2
您的帖子似乎没有提供任何关于如何创建MetroWindow的新窗口的指示。Caliburn的默认WindowManager始终创建Windows,而不是MetroWindows。您有解决方案吗? - George

6
似乎 SizeToContent 是问题所在!

也许你应该将其标记为答案,如果相关的话,可以添加更多信息? - Simon Halsey
1
对于那些感兴趣的人,似乎只需删除“SizeToContent = SizeToContent.WidthAndHeight”即可解决问题。 - korbes

3
解决这个问题的方法是将 ResizeMode 属性设置为 "NoResize",然后边框会正常渲染。
window = new MetroWindow()
{
    Content = view,
    SizeToContent = SizeToContent.WidthAndHeight,
    ResizeMode = ResizeMode.NoResize
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接