もっと詳しく

以前、こちらの記事にてWPFで使えるドッキングウィンドウ「AvalonDock」の詳しい使い方を紹介しました。

2021年11月9日に.NET Core と .NET Framework を統合した .NET 6.0がリリースされたことで、今後は .NET 6.0 をFramework とした開発が主流になっていきます。

実際の開発プロジェクトの場合、現段階で.NET 6.0へ移行することは費用対効果の観点から当面は様子見となりがちですが、趣味の世界なら自分の気持ち一つで何とでもなります。

ということで今回は、過去のプログラムを.NET 6.0 に移植してみたところ、.NET Framework で普通に使えていたAvalonDockが突然エラーを吐いて動かなくなったので、その解決方法について解説したいと思います。

見舞われた現象は、プログラム実行時のエラー

まず最初に、「WpfApp1」という名前でプロジェクトを作成します。 

次に、NuGetで「avalon dock」というキーワードで表示されたリストの中から、「Xceed.Products.Wpf.Toolkit.AvalonDock」を選んでインストールします。

そして、XAMLに下記のコードを張りけます。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:avalonDock="http://schemas.xceed.com/wpf/xaml/avalondock"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <avalonDock:DockingManager x:Name="uxDockingManager" AllowMixedOrientation="True" Grid.Row="1">
            <avalonDock:LayoutRoot>
                <avalonDock:LayoutPanel Orientation="Vertical" >
                    <avalonDock:LayoutPanel Orientation="Horizontal">
                        <avalonDock:LayoutDocumentPane x:Name="uxDocumentPane">
                            <!-- ドキュメント  ★ここから-->
                            <avalonDock:LayoutDocument Title="Document1" ContentId="Document1">
                                <TextBox/>
                            </avalonDock:LayoutDocument>
                            <!-- ドキュメント ★ここまで-->
                        </avalonDock:LayoutDocumentPane>
                    </avalonDock:LayoutPanel>
                    <avalonDock:LayoutAnchorablePane DockHeight="100"  x:Name="uxAnchorablePane2">
                        <!-- ツールウィンドウ -->
                        <avalonDock:LayoutAnchorable Title="ToolWindow2" ContentId="ToolWindow2">
                            <TextBox/>
                        </avalonDock:LayoutAnchorable>
                    </avalonDock:LayoutAnchorablePane>
                </avalonDock:LayoutPanel>
            </avalonDock:LayoutRoot>
        </avalonDock:DockingManager>
    </Grid>
</Window>

この状態で「実行」を行うと、画面が開く前に下記のエラーが発生してしまいます。

原因は Xceed.Avalon.Dockのライセンスが必要だから

どうやら、 Xceed.Products.Wpf.Toolkit.AvalonDock を .NET 6.0 で使う場合は、十数万円の開発者ライセンスを別途購入する必要があるようです。

また、45日間は無料お試しと書かれていますが、お試し用のライセンスキーを取得しないとエラーが解決できません。

解決策は Dirkster.Avalon.Dockを使う事

最初にNugetで検索した際、「Xceed.Products.Wpf.Toolkit.AvalonDock」 の上に「Dirkster.AvalonDock」というものがヒットしていました。

こちらも同じAvalonDockなのですが、Microsoft Public License (Ms-PL) というオープンソースの一種で、別途ライセンスの購入は必要ありません。

ちなみに、GitHubにはソースがアップされていました。

ということで、 「Dirkster.AvalonDock」をインストールすることで解決です。

Dirkster.Avalon.Dockの使い方の注意点

「Xceed.Products.Wpf.Toolkit.AvalonDock」 と「Dirkster.AvalonDock」はほとんど同じなので、 こちら の記事に記載している内容がほぼそのまま適用できます。

ほんの少しだけ異なる点があるので、ここではその点について解説しておきます。

avalonDock のネームスペースの変更が必要

XceedのAvalonDockからDirkesterのAvalonDockに変更するには、ネームスペースを下記の様に記述する必要があります。

xmlns:avalonDock="https://github.com/Dirkster99/AvalonDock"

コードからテーマを設定する際の記述が異なる

XAMLでテーマを設定する場合は Xceed と Dirksterのどちらも同じで、下記の様に記述できます。

<avalonDock:DockingManager.Theme>
      <avalonDock:GenericTheme/>
</avalonDock:DockingManager.Theme>

一方、コードでテーマを登録する場合は、下記の様に記述する必要があります。

※ uxDockingManager は XAML上でAvalonDockに付けた名前avalonDock:DockingManager x:Name=”uxDockingManager”

uxDockingManager.Theme = new AvalonDock.Themes.GenericTheme()

XAMLでAvalonDockの構造を定義してもレイアウトエディタに表示されない

これはどちらのバグか、あるいは仕様なのか不明ですが、XAMLにAvalonDockの構造(レイアウト)を張り付けた瞬間はVisual Studioのレイアウトエディタ上に表示されますが、すぐに表示されなくなります。

実行時にはちゃんと表示されるので、これくらいは我慢しましょう。

AvalonDockで使えるテーマが増えていた

NuGet で「Dirkster.Avalon.Dock」で検索すると、以下の通り使えるテーマが表示されます。

必要に応じてインストールしてみて下さい。

ちなみに、2022年1月現在で使えるテーマは次の通りです。

サンプルコード

Dirkster.Avalon.Dock を使ったサンプルコードを掲載しておきます。

画面のコンボボックスからテーマを変更することが出来るので、プログラムを実行したい方は、全てのテーマをインストールしておいてください。

まずXAMLのコードです。

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:avalonDock="https://github.com/Dirkster99/AvalonDock"
        xmlns:local="clr-namespace:WpfApp1" 
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="600">
    <Grid>
        <avalonDock:DockingManager x:Name="uxDockingManager" AllowMixedOrientation="True" Margin="0,37,0,0">
            <avalonDock:DockingManager.Theme>
                <avalonDock:GenericTheme/>
            </avalonDock:DockingManager.Theme>
            <avalonDock:LayoutRoot>
                <avalonDock:LayoutPanel Orientation="Vertical" >
                    <avalonDock:LayoutPanel Orientation="Horizontal">
                        <avalonDock:LayoutDocumentPane x:Name="uxDocumentPane">
                            <!-- ドキュメント  ★ここから-->
                            <avalonDock:LayoutDocument Title="Document1" ContentId="Document1">
                                <TextBox/>
                            </avalonDock:LayoutDocument>
                            <!-- ドキュメント ★ここまで-->
                        </avalonDock:LayoutDocumentPane>
                    </avalonDock:LayoutPanel>
                    <avalonDock:LayoutAnchorablePane DockHeight="100"  x:Name="uxAnchorablePane2">
                        <!-- ツールウィンドウ -->
                        <avalonDock:LayoutAnchorable Title="ToolWindow2" ContentId="ToolWindow2">
                            <TextBox/>
                        </avalonDock:LayoutAnchorable>
                    </avalonDock:LayoutAnchorablePane>
                </avalonDock:LayoutPanel>
            </avalonDock:LayoutRoot>
        </avalonDock:DockingManager>
        <ComboBox Margin="0,8,18,0" VerticalAlignment="Top" x:Name="uxSelectTheme" SelectedValuePath="Content" HorizontalAlignment="Right" Width="120" SelectionChanged="uxSelectTheme_SelectionChanged">
            <ComboBoxItem >GenericTheme</ComboBoxItem>
            <ComboBoxItem >MetroTheme</ComboBoxItem>
            <ComboBoxItem >AeroTheme</ComboBoxItem>
            <ComboBoxItem >ExpressionDarkTheme</ComboBoxItem>
            <ComboBoxItem >ExpressionLightTheme</ComboBoxItem>
            <ComboBoxItem >VS2010Theme</ComboBoxItem>
            <ComboBoxItem >Vs2013BlueTheme</ComboBoxItem>
            <ComboBoxItem >Vs2013DarkTheme</ComboBoxItem>
            <ComboBoxItem >Vs2013LightTheme</ComboBoxItem>
        </ComboBox>

    </Grid>
</Window>

C#のコードです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void uxSelectTheme_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            switch (uxSelectTheme.SelectedValue.ToString())
            {
                case "GenericTheme": uxDockingManager.Theme = new AvalonDock.Themes.GenericTheme(); break;
                case "MetroTheme": uxDockingManager.Theme = new AvalonDock.Themes.MetroTheme(); break;
                case "AeroTheme": uxDockingManager.Theme = new AvalonDock.Themes.AeroTheme(); break;
                case "ExpressionDarkTheme": uxDockingManager.Theme = new AvalonDock.Themes.ExpressionDarkTheme(); break;
                case "ExpressionLightTheme": uxDockingManager.Theme = new AvalonDock.Themes.ExpressionLightTheme(); break;
                case "VS2010Theme": uxDockingManager.Theme = new AvalonDock.Themes.VS2010Theme(); break;
                case "Vs2013BlueTheme": uxDockingManager.Theme = new AvalonDock.Themes.Vs2013BlueTheme(); break;
                case "Vs2013DarkTheme": uxDockingManager.Theme = new AvalonDock.Themes.Vs2013DarkTheme(); break;
                case "Vs2013LightTheme": uxDockingManager.Theme = new AvalonDock.Themes.Vs2013LightTheme(); break;
            }
        }

    }
}

まとめ

今回は WPF用のドッキングウィンドウ「 Xceed.Products.Wpf.Toolkit.AvalonDock 」を .NET 6.0 で使おうとしたら、実行時にライセンスが無いと言ってエラーで落ちてしまうので、その解決策として「 Dirkster.AvalonDock 」を使う方法を紹介しました。

「 Dirkster.AvalonDock 」 は Microsoft Public License (Ms-PL) というオープンソースのライセンスであり、2021年12月24日(クリスマス)に更新されているので、おそらく今後も安心して使うことが出来ると思われます。

.NET6.0 でドッキングウィンドをお探しの方は、是非こちらを活用してみて下さい。

この記事が皆さんの一助となれば幸いです。