.NET Core 3.1 WPF : コントロールの作成(1)
viewとviewModelは疎結合であるべき、は同意だが、あまり真面目にそこに取り組むつもりはない。 UI要素そのものがオプションやユーザー操作で動的に変化するアプリケーションがMVVMで記述できるのかも不明。 xamlの記述だけではsplitterすら満足な動作が困難に感じたので、コードビハインド(.xaml.csのこと、みたい)にも気にせずUIを記述することにする。
MVVMの問題など: MVVMを少し調べてみる - 負け犬プログラマーの歩み
■project
vsの新規作成から
ここではプロジェクト"XAMLtest"とする。ソースは以下の通りに自動作成される。
■MainWindow.xaml
基本的な記述はクラス定義、クラス保有のリソース定義、そしてUIの構造定義を記述する。 他にも有用な要素があるかもしれない。visual studioのデザイナで全てを構築できるのかは不明。
WPF4.5入門 その7 「XAMLのオブジェクト要素と名前空間」 - かずきのBlog@hatena
●WPF xamlの詳細
第4回 WPFの「リソース、スタイル、テンプレート」を習得しよう:連載:WPF入門(1/3 ページ) - @IT
●全体
サンプルコードは以下の通り。
<!-- クラス定義 --> <Window x:Class="XAMLtest.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:local="clr-namespace:XAMLtest" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <!-- リソース設定 --> <Window.Resources> <SolidColorBrush x:Key="brush0" Color="LightGray"/> <SolidColorBrush x:Key="brush1" Color="Gray"/> </Window.Resources> <!-- Window --> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="36" /> <RowDefinition Height="24" /> <RowDefinition Height="36" /> </Grid.RowDefinitions> <Label Grid.Row="0" Name="abc" Content="xxx" Background="#c08040"/> <Button Grid.Row="1" Content="btn0" Background="{StaticResource brush0}"/> <Button Grid.Row="2" Content="btn1" Background="{StaticResource brush1}"/> <TextBox Grid.Row="3" Text="aaa"/> </Grid> </Window>MainWindow.xaml
●クラス定義部分
コード前半はクラス定義、中はnamespaceのエイリアス定義などが自動で記述されている。
<!-- クラス定義 --> <Window x:Class="fileListView.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:local="clr-namespace:fileListView" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800" ResizeMode="CanResizeWithGrip">MainWindow.xaml
C#で書けば以下のような感じだろうか。
// defaultのnamespace using namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation; // その他のnamespaceのエイリアス using x = http://schemas.microsoft.com/winfx/2006/xaml; using d = http://schemas.microsoft.com/expression/blend/2008; ... using local = fileListView; // projectのnamespace // class define namespace fileListView { // <Window x:Class="fileListView.MainWindow>に相当 public class MainWindow : System.Windows.Window { ... MainWindow() { Height = 450; // System.Windows.FrameworkElement.Height Width = 800; // System.Windows.FrameworkElement.Width ... InitializeComponent(); } }; }
●リソース定義部分
コード中盤はリソース定義、後半のウインドウのコントロール定義部分から参照できる。 リソース自体もstaticに記述したり、外部ファイルから取り込む、マージする、などができるようだが、詳細は先のリンクに。
ResourcesプロパティはSystems.Windows.FrameworkElement.Resourcesなので、Windowに限らず様々なcotnrolが独自に持つことができる。 親子に同名のキーで定義される場合、親方向に近い世代のリソースが適用される。
<!-- クラス定義 --> <!-- リソース設定 --> <Window.Resources> <SolidColorBrush x:Key="brush0" Color="LightGray"/> <SolidColorBrush x:Key="brush1" Color="Gray"/> </Window.Resources>MainWindow.xaml
ResourceDictionary Resources なので、Item[]を持っているのでobjectを保持しているはずだが、例えばstringなどを定義しようとすると次のようなエラーが。
WPFで定められているクラスを、IDictionnaryで検索する"x:Key"で定義する必要があるようだが、どのクラスが管理されているのかは不明。
●コントロール定義部分
コード後半はコントロール定義、ここではWindowの中身の配置を定義する。
<!-- Window --> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="36" /> <RowDefinition Height="24" /> <RowDefinition Height="36" /> </Grid.RowDefinitions> <Label Grid.Row="0" Name="abc" Content="xxx" Background="#c08040"/> <Button Grid.Row="1" Content="btn0" Background="{StaticResource brush0}"/> <Button Grid.Row="2" Content="btn1" Background="{StaticResource brush1}"/> <TextBox Grid.Row="3" Text="aaa"/> </Grid>MainWindow.xaml
StaticResourceによってリソースをバインドしている部分が重要。
Gridをテストとして使用。RowDefinitionsでstretchさせるコントロールの指定は"*"で示す。
プロパティにリソースを割り当てるのもリストの通り。
コントロールのプロパティ→リソース定義→コードビハインドにバインドし、ダイナミックに内容を変更するのが一つの目標になる。
■todo
クラスの継承、プロパティの優先順位、その他の不明瞭なルールなど果てしなく存在している。