WPFメモ　Caliburn.Micro

# 概要

Caliburn.Microを触ってみた。

# 環境

* Visual Studio 2019 Community

# 1. プロジェクト作成

C#, WPFプロジェクトを`CalSample`の名前で新規作成した。

![cal01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/1fb582f9-aca4-0e11-e161-aaff17fe39eb.png)

# 2. NuGet

NuGetで`Caliburn.Micro`をインストール。

![cal02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/ee0cf1cd-8c66-42c7-c1f6-dd10cf98b9d0.png)

# 3. 使わないもの削除

MainWindowを削除、App.xamlから`StartupUri`の記述を削除。

![cal03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/24040795-075a-5508-634f-79351e57cacc.png)

# 4. ビューモデル作成

`ViewModels`と`Views`フォルダを作成。

![cal04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/834ac5e5-80e6-8cb6-1347-c2628c5cee88.png)

`ViewModels`フォルダには IShell.cs と ShellViewModel.cs を作成。

```CSharp:IShell.cs
namespace CalSample.ViewModels
{
    interface IShell
    {
        string Name1 { get; set; }
        string Name2 { get; set; }
        bool CanShowName { get; }
        void ShowName();
    }
}
```

```CSharp:ShellViewModel.c
namespace CalSample.ViewModels
{
    public class ShellViewModel : Caliburn.Micro.PropertyChangedBase, IShell
    {
        private string name1;
        public string Name1
        {
            get => name1;
            set
            {
                name1 = value;
                NotifyOfPropertyChange(() => Name1);
                NotifyOfPropertyChange(() => CanShowName);
            }
        }

        public string Name2 { get; set; }

        public bool CanShowName => !string.IsNullOrWhiteSpace(Name1);

        /// <summary>
        /// 名前表示
        /// </summary>
        public void ShowName()
        {
            System.Windows.MessageBox.Show($"こんにちは、{Name1} {Name2}さん。");
        }
    }
}
```

# 5. ブートストラッパー作成

![cal05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/17ecbf22-da8c-539d-4cc3-c4b33bbf8904.png)

```CSharp:AppBootStrapper.cs
using Caliburn.Micro;
using System;
using System.Collections.Generic;

namespace CalSample
{
    public class AppBootStrapper : BootstrapperBase
    {
        SimpleContainer container;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public AppBootStrapper()
        {
            Initialize();
        }

        protected override void Configure()
        {
            container = new SimpleContainer();

            container.Singleton<IWindowManager, WindowManager>();
            container.Singleton<IEventAggregator, EventAggregator>();
            container.PerRequest<ViewModels.IShell, ViewModels.ShellViewModel>();
        }

        protected override object GetInstance(Type service, string key)
        {
            return container.GetInstance(service, key);
        }

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

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

        protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
        {
            // ルートビューモデルの指定
            DisplayRootViewFor<ViewModels.IShell>();
        }
    }
}
```

```Xml:App.xaml
<Application x:Class="CalSample.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:CalSample">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary>
                    <local:AppBootStrapper x:Key="bootstrapper"/>
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>
```

# 6. ビューの作成

`Views`フォルダ内に`ShellView`の名前で新規ウィンドウを作成、`ShellView.xaml.cs`を削除。

![cal06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/0f61d8ae-debe-f407-051f-687773ad335f.png)

画面を作成する

![cal07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/c05dcd06-d5b7-281a-4cd7-223c746bdb0b.png)

```Xml:ShellView.xaml
<Window x:Class="CalSample.Views.ShellView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:cal="http://www.caliburnproject.org"
        Height="150" Width="450" ResizeMode="CanResizeWithGrip">

    <Window.Resources>
        <Style x:Key="TextLabelStyle" TargetType="TextBlock">
            <Setter Property="Margin" Value="5,5,0,0"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
        </Style>
        <Style x:Key="InputTextStyle" TargetType="TextBox">
            <Setter Property="Margin" Value="5,5,0,0"/>
            <Setter Property="Width" Value="150"/>
        </Style>
        <Style x:Key="ButtonStyle" TargetType="Button">
            <Setter Property="Margin" Value="5,5,0,0"/>
        </Style>
    </Window.Resources>

    <WrapPanel FocusManager.FocusedElement="{Binding ElementName=nameInput1}">
        <TextBlock 
            Text="お名前" 
            Style="{StaticResource TextLabelStyle}"/>
        <TextBox 
            x:Name="nameInput1" 
            Text="{Binding Name1, UpdateSourceTrigger=PropertyChanged}" 
            Style="{StaticResource InputTextStyle}" />

        <!-- ViewModelのName2にバインド -->
        <TextBox 
            x:Name="Name2"
            Style="{StaticResource InputTextStyle}" />

        <!-- ClickイベントはViewModelのShowNameメソッドを呼び出す -->
        <Button 
            Content="挨拶" 
            cal:Message.Attach="ShowName" 
            IsDefault="True" 
            Style="{StaticResource ButtonStyle}"/>
    </WrapPanel>
</Window>
```

# 7. 実行してみる

![cal08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/399651f2-e805-1070-4f0e-2b5427172c63.png)

1つ目のテキストボックスに入力するとボタンが押せるようになる。

![cal09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/b4c5f778-f89a-544e-e857-86dc600b47d0.png)

2つ目のテキストボックスにも入力してボタンを押した。

![cal10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142879/a91f99cc-c865-cbcf-238e-172a45a73fba.png)