ネタ元1:http://bbs.wankuma.com/index.cgi?mode=al2&namber=42894
ネタ元2:http://social.msdn.microsoft.com/Forums/ja-JP/vbgeneralja/thread/dd3810a9-e3aa-4706-89ee-3f836408e709
Windows Formの頃には一般的?に行われていたFormの継承を、WPFでやろうとすると躓きます。これは、ネタ元を見ていただければわかると思います。
じゃぁどうやるの?ということで強引にしてみました。
Windowをベースにしたカスタムコントロールを作る
まず、WPFアプリケーションのプロジェクトでカスタムコントロールを作成します。
ここでは、MyWindowという名前にしました。そして、基本クラスをControlからWindowに変更します。
using System.Windows; using System.Windows.Media; namespace WpfBaseWindow { // 基本クラスはWindowにする public class MyWindow : Window { static MyWindow() { DefaultStyleKeyProperty.OverrideMetadata(typeof(MyWindow), new FrameworkPropertyMetadata(typeof(MyWindow))); // 背景色をWindowBrushにしておく BackgroundProperty.OverrideMetadata(typeof(MyWindow), new FrameworkPropertyMetadata(SystemColors.WindowBrush)); } } }
そして、Generic.xamlに、見た目を作っていきます。
<?xml version="1.0" encoding="Shift_JIS"?> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfBaseWindow"> <Style TargetType="{x:Type local:MyWindow}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:MyWindow}"> <!-- ここに見た目を作っていく --> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> <!-- 今回は、ヘッダーとフッターに文字を出すだけにします --> <DockPanel> <TextBlock DockPanel.Dock="Top" Text="へっだー" /> <TextBlock DockPanel.Dock="Bottom" Text="ふったー" /> <!-- センターにコンテンツ(つまり継承先のWindowで追加されるコントロール)を 表示するようにします --> <ContentPresenter /> </DockPanel> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
Generic.xamlの頭にShift_JISであることを宣言しておかないと、日本語が使えないので要注意です。(ここらへんはXMLのお話だけど)
Windowの親クラスを差し替える
ついにWindowの親クラスを差し替えます。最初にWindow1.xamlのルートのタグをWindowからlocal:MyWindowに変更します。localは、MyWindowの所属する名前空間とマッピングするようにxmlnsを定義しておきます。
<local:MyWindow x:Class="WpfBaseWindow.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfBaseWindow" Title="Window1" Height="300" Width="300"> <Grid> <Button Content="aaaaa" /> </Grid> </local:MyWindow>
ついでにボタンも1つ置いておきました。
この状態でビルドすると、
'WpfBaseWindow.Window1' の partial 宣言では、異なる基本クラスを指定してはいけません。
というエラーで怒られてしまいます。
これは、Window1.xaml.csでWindow1 : Windowと明示的に継承が書かれているせいです。これをMyWindowに変えてしまいましょう。
using System.Windows; namespace WpfBaseWindow { /// <summary> /// Window1.xaml の相互作用ロジック /// </summary> public partial class Window1 : MyWindow { public Window1() { InitializeComponent(); } } }
ちゃんと見た目が継承されています。
感想
やる必要があるのかというと、そうでもないかな〜という感じがします。
個人的には、Windowを1つ作っておいて、固有の部分をUserControlで作っていって差し替えるといった感じでやっていくと思います。
それにModel-View-ViewModelパターンでさくっと出来そう。