for WPF developers
Home Profile Tips 全記事一覧

デザイン実行かどうかを判定する

(2017/04/26 8:04:29 created.)

(2017/05/24 16:58:05 modified.)

デザイン実行とは、XAML デザイナーがバックグラウンドでコードを解析・実行することです。このおかげで XAML デザイナー上の表示がリアルタイムに変化しています。

ユーザーコントロールやカスタムコントロールを配置するとき、そのコンテンツに動的なデータがある場合、デザイン実行ではまだアプリケーションは動いていないため、デザイン実行中に予期せぬエラーや例外が発生してしまい、XAML デザイナー上で画面の確認ができなくなってしまいます。このようなことが起きないようにするために、デザイン実行かどうかをコードで判断することができます。

Signals.xaml
  1. <UserControl x:Class="Tips_XamlDesigner.Views.Signals"
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  6.              mc:Ignorable="d" 
  7.              d:DesignHeight="300" d:DesignWidth="300">
  8.     <StackPanel Orientation="Horizontal">
  9.         <Ellipse Width="20" Height="20" Margin="5" Fill="Green" />
  10.         <Ellipse Width="20" Height="20" Margin="5" Fill="Yellow" />
  11.         <Ellipse Width="20" Height="20" Margin="5" Fill="Red" />
  12.         <TextBlock x:Name="textblock1" Text="Signals" VerticalAlignment="Center" />
  13.     </StackPanel>
  14. </UserControl>
Signals.xaml.cs
  1. namespace Tips_XamlDesigner.Views
  2. {
  3.     using System.Windows.Controls;
  4.  
  5.     /// <summary>
  6.     /// Signals.xaml の相互作用ロジック
  7.     /// </summary>
  8.     public partial class Signals : UserControl
  9.     {
  10.         public Signals()
  11.         {
  12.             InitializeComponent();
  13.  
  14.             if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
  15.             {
  16.                 this.textblock1.Text = "デザインモード";
  17.             }
  18.         }
  19.     }
  20. }

XAML 上で "Signals" というテキストを持つ TextBlock コントロールに対し、コードビハインドでは、ある条件によって "デザインモード" というテキストに変更するコードが組み込まれています。

System.ComponentModel.DesignerProperties クラスは、デザイナーとの通信に使用される添付プロパティを提供しています。そして、IsDesignMode という添付プロパティで、対象とするオブジェクトのインスタンスがデザイナーのコンテキストで実行されているかどうかを確認することができます。

IsDesignMode は添付プロパティなので、プロパティ名の頭に "Get" を付けた GetIsDesignMode() メソッドでプロパティ値を取得することができます。したがって、14 行目のように、引数にユーザーコントロール自身を示す this を指定して IsDesignMode 添付プロパティの値を取得することで、デザインモードかどうかを判定することができます。

このユーザーコントロールをウィンドウに配置してみましょう。XAML コードは次のようになります。

MainView.xaml
  1. <Window x:Class="Tips_XamlDesigner.Views.MainView"
  2.         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3.         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4.         xmlns:vw="clr-namespace:Tips_XamlDesigner.Views"
  5.         Title="MainView" Height="300" Width="300">
  6.     <StackPanel>
  7.         <vw:Signals />
  8.         <vw:Signals />
  9.     </StackPanel>
  10. </Window>

実行するとユーザーコントロールの XAML で定義したように、"Signals" というテキストが表示されていますが、


XAML デザイナー上ではコードビハインドで変更された文字列になっていることがわかります。


このサンプルでは静的なデータを書き換えるのみでしたが、実行しないと取得できない動的なデータなどに対して、デザインモードの場合には仮の値を入れておくようにしておくなどしておけば、XAML デザイナーがエラーを出力することなく画面が確認できるようになります。

また、Window や UserControl など View に関するインスタンスが取得できない場合、GetIsDesignMode() メソッドの引数に DependencyObject を渡すことができません。この場合は次のような方法でデザイン実行かどうかを判定します。

Sample.cs
  1. if ((bool)(System.ComponentModel.DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(System.Windows.DependencyObject)).DefaultValue))
  2. {
  3.     // デザイン実行時は処理しない
  4.     return;
  5. }