はじめに
15年ぶりのプログラミング勉強(C#)を始めて、昨年自社アプリを作りました。
この時使用したのは、C#、WPF、Prism、.NET Framework4.8でした。
勉強しながら半分趣味で作ったので、勉強の進捗に合わせるように古いものほど中身がひどく、作り直したい気分です。
最近Microsoftから.NET5が出たので、今度はそのアプリを.NET5対応にしていこうと思っています。
今まで使ったことのない技術など取り入れながら、そこでぶつかった問題や解決したことを描いていければと思います。
DataTemplateSelectorを使ったらエラーになってしまった
エラーとなった部分はこんな感じ
<StackPanel Margin="15">
<TextBlock Text="{Binding Message}"/>
<ContentControl Content="{Binding}"
ContentTemplateSelector="{StaticResource MessageDialogTemplateSelector}"/>
</StackPanel>
すると、ContentControlのところに波線が出て、"XDG0066 Object reference not set to an instance of an object." (オブジェクト参照がオブジェクトインスタンスに設定されていません)となってしまいました。
利用したDataTemplateは
<UserControl.Resources>
<DataTemplate x:Key="OkOnlyTemplate">
<Button Content="OK" Command="{Binding OkCommand}"/>
</DataTemplate>
<DataTemplate x:Key="YesNoTemplate">
<StackPanel Orientation="Horizontal">
<Button Content="Yes" Command="{Binding YesCommand}"/>
<Button Content="No" Command="{Binding NoCommand}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="OkCancelTemplate">
<StackPanel Orientation="Horizontal">
<Button Content="OK" Command="{Binding OkCommand}"/>
<Button Content="Cancel" Command="{Binding CancelCommand}"/>
</StackPanel>
</DataTemplate>
<templateSelectors:MessageDialogTemplateSelector
x:Key="MessageDialogTemplateSelector"
OkOnlyTemplate="{StaticResource OkOnlyTemplate}"
YesNoTemplate="{StaticResource YesNoTemplate}"
OkCancelTemplate="{StaticResource OkCancelTemplate}"/>
</UserControl.Resources>
簡単なメッセージボックスを自作しようと思ったのですが、何がなんだか・・・と困惑。
ただ、ビルド実行はできました。
原因
原因としては、Visual Studioのデザインビューを表示しようとしても、ContentControlに表示する内容が、デザイン時には決まっていないため、デザインビューを表示できないということのようでした。
じゃあ ContentTemplateをしてしまえばいいのでは?と思いましたが、MicrosoftのドキュメントでContentTemplateSelectorプロパティとプロパティの両方 ContentTemplate が設定されている場合、このプロパティは無視されますとの記述が・・・
解決
ビルドは実行できるし、このまま放っておこうか(笑)と思っていましたが、XAMLでデザイン時だけ使うというものがあったことを思い出しました。
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
これで、ContentControlのContentTemplateを設定してしまえばいいのでは?
<StackPanel Margin="15">
<TextBlock Text="{Binding Message}"/>
<ContentControl Content="{Binding}"
d:ContentTemplate="{StaticResource OkOnlyTemplate}"
ContentTemplateSelector="{StaticResource MessageDialogTemplateSelector}"/>
</StackPanel>
これでエラーがなくなり、デザインビューも表示できるようになりました。