04-ViewDiscovery
Descriptionには Automatically inject views with View Discovery とあります。
やっと動きがありました。とはいえ、アプリケーションを動かしても「View A」と表示されるだけですけどね…
App.xaml
<prism:PrismApplication
x:Class="ViewDiscovery.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewDiscovery"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources />
</prism:PrismApplication>
App.xaml.cs
using System.Windows;
using ViewDiscovery.Views;
namespace ViewDiscovery
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : PrismApplication
{
protected override Window CreateShell()
{
return Container.Resolve<MainWindow>();
}
protected override void RegisterTypes(IContainerRegistry containerRegistry) { }
}
}
MainWindow.xaml
<Window
x:Class="ViewDiscovery.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="Shell"
Width="525"
Height="350">
<Grid>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace ViewDiscovery.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow(IRegionManager regionManager)
{
InitializeComponent();
//view discovery
regionManager.RegisterViewWithRegion("ContentRegion", typeof(ViewA));
}
}
}
ここで、ContentRegion
にリージョン ViewA
を割りあてているのでしょう。
…というか、この引数は CommunityToolkit.Mvvm におけるコンストラクタ注入のようですね?
ViewA.xaml
<UserControl
x:Class="ViewDiscovery.Views.ViewA"
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:local="clr-namespace:ViewDiscovery.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="300"
mc:Ignorable="d">
<Grid>
<TextBlock FontSize="38" Text="View A" />
</Grid>
</UserControl>
そして、MainWindow.xaml.cs 経由で、この ViewA.xaml にある「View A」を表示しています。実際に
<TextBlock FontSize="38" Text="View A" />
の Text
の内容を書き換えれば、アプリケーションでの表示が変わります。
このサンプルはこの程度でいいでしょう、次行きますよ次!
05-ViewInjection
Descriptionには Manually add and remove views using View Injection とあります。
ビルドして実行すると「Add View」ボタンがあり、これをクリックすると ViewA
が表示されます。
App.xaml.cs と ViewA.xaml
前節と同じです。
App.xaml
<prism:PrismApplication
x:Class="ViewInjection.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ViewInjection"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources />
</prism:PrismApplication>
MainWindow.xaml
<Window
x:Class="ViewInjection.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="Shell"
Width="525"
Height="350">
<DockPanel LastChildFill="True">
<Button Click="Button_Click" DockPanel.Dock="Top">Add View</Button>
<ContentControl prism:RegionManager.RegionName="ContentRegion" />
</DockPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace ViewInjection.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly IContainerExtension _container;
private readonly IRegionManager _regionManager;
public MainWindow(IContainerExtension container, IRegionManager regionManager)
{
InitializeComponent();
_container = container;
_regionManager = regionManager;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var view = _container.Resolve<ViewA>();
IRegion region = _regionManager.Regions["ContentRegion"];
region.Add(view);
}
}
}
ここで、private readonly
を追記しています。
やはり MainWindow
はコンストラクタ注入のようですね?
ボタンがクリックされたら、ContentRegion
リージョンにコンテナに ViewA
を追加している、という処理に見えます…
まあ、考えていても分からない物は分からない!次行きますよ次!
06-ViewActivationDeactivation
Descriptionには Manually activate and deactivate views とあります。
ここに来て一気に動く物が来ました。
「Activate ViewA」「Activate ViewB」で ViewA
や ViewB
をアクティブにして
「Deactivate ViewA」「Deactivate ViewB」でアクティブにされている View を無効にしています。
ここできちんと動かせば分かるのですが 「Activate ViewA」→「Activate ViewB」→「Deactivate ViewB」としても、ViewAがアクティブになるわけではありません。
それでは、少し丁寧にソースを追いかけてみましょう。
App.xaml.cs と ViewA.xaml
前節と同じです。
ViewB.xaml
基本的に ViewA.xaml と同一で、以下の部分だけが異なっています。
<TextBlock FontSize="38" Text="View B" />
App.xaml
<prism:PrismApplication
x:Class="ActivationDeactivation.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ActivationDeactivation"
xmlns:prism="http://prismlibrary.com/">
<Application.Resources />
</prism:PrismApplication>
MainWindow.xaml
<Window
x:Class="ActivationDeactivation.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
Title="Shell"
Width="525"
Height="350">
<DockPanel LastChildFill="True">
<StackPanel>
<Button Click="Button_Click" Content="Activate ViewA" />
<Button Click="Button_Click_1" Content="Deactivate ViewA" />
<Button Click="Button_Click_2" Content="Activate ViewB" />
<Button Click="Button_Click_3" Content="Deactivate ViewB" />
</StackPanel>
<ContentControl
HorizontalAlignment="Center"
VerticalAlignment="Center"
prism:RegionManager.RegionName="ContentRegion" />
</DockPanel>
</Window>
MainWindow.xaml.cs
using System.Windows;
namespace ActivationDeactivation.Views
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private readonly IContainerExtension _container;
private readonly IRegionManager _regionManager;
IRegion _region;
ViewA _viewA;
ViewB _viewB;
public MainWindow(IContainerExtension container, IRegionManager regionManager)
{
InitializeComponent();
_container = container;
_regionManager = regionManager;
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
_viewA = _container.Resolve<ViewA>();
_viewB = _container.Resolve<ViewB>();
_region = _regionManager.Regions["ContentRegion"];
_region.Add(_viewA);
_region.Add(_viewB);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//activate view a
_region.Activate(_viewA);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
//deactivate view a
_region.Deactivate(_viewA);
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
//activate view b
_region.Activate(_viewB);
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
//deactivate view b
_region.Deactivate(_viewB);
}
}
}
いや、サンプルとは言えコードビハインドの命名が酷いですね…ああ、前回と同様に private readonly
を追記しています。
肝となるのはこのコードですね。
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
_viewA = _container.Resolve<ViewA>();
_viewB = _container.Resolve<ViewB>();
_region = _regionManager.Regions["ContentRegion"];
_region.Add(_viewA);
_region.Add(_viewB);
}
こうすることで、_region
には ViewA
と ViewB
の二つ View が入るわけですが、同時に使われる訳じゃなさそうです。
排他的に Activate()
で有効化されて、有効化された View に対してだけ Deactivate()
が実行される訳ですね。
で、Deactivate()
は無効化されるだけで、_region
では相変わらず使える訳です。
一旦締めます
とりあえず、region については正直「わかったような、わからないような…?」という印象が拭えません。
ざっくり「複数のViewを登録して、切り替えられる」という認識で良さそうですね。
致命的な誤りがあった場合、フィードバックをしていただけると幸いです。
次は、サンプルから一旦離れて、Prism を使った View のコードを書いてみます。