Window
C#やVisual BASICなんかで書けば、Applicationタグというものもあるのですが、Iron Pythonを使っている限り、 唯一のルート要素です。このWindowについて説明します。WPFのすべてのウィンドウの基本型はSystem.Windows.Windowです。Windowは、アプリケーションのトップレベルコンテンツを ホストするために設定されたコントロールです。通常はXAMLファイルの中でプロパティを、スクリプトファイルで イベントを定義します。
XAMLファイル(window1.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="一番簡単なWindow">
</Window>
スクリプトファイル
import wpf
from System.Windows import Application, Window
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'window1.xaml')
if __name__ == '__main__':
Application().Run(MyWindow())
Windowのイベント
Windowが作成されてから閉じられるまでに発生するイベントは次の通りです。1) __INIT__が呼び出される。
2) Showメゾットが呼び出される。
(Initializedイベントが発生する。)
3) Loadedイベントが発生する。
4) ContentRenderedイベントが発生する。
5) ?Activatedイベントが発生する。
6) ユーザーがウィンドウを操作する。
7) Closingイベントが発生する。
8) ?Deactivatedイベントが発生する。
9) Unloadedイベントが発生する。
10) Closedイベントが発生する。
調べた資料には、Initializedイベントのことやイベントの順番が別で書かれていましたが 私が下記のScriptファイルで実行した結果は上の順番でした。
XAMLファイル(window2.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="window2" Height="300" Width="300">
</Window>
スクリプトファイル
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox
import wpf
from System.Windows import Application, Window
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'window2.xaml')
self.Initialized += self.MyWin_Initialized
self.LocationChanged += self.MyWin_LocationChanged
# self.Activated += self.MyWin_Activated
self.Loaded += self.MyWin_Loaded
self.ContentRendered += self.MyWin_ContentRendered
self.Closing += self.MyWin_Closing
# self.Deactivated += self.MyWin_Deactivated
self.Closed += self.MyWin_Closed
self.Unloaded += self.MyWin_Unloaded
def MyWin_Initialized(self, sender, e):
MessageBox.Show("Initializedイベントが発生")
def MyWin_LocationChanged(self, sender, e):
MessageBox.Show("LocationChangedイベントが発生")
def MyWin_Activated(self, sender, e):
MessageBox.Show("Activatedイベントが発生")
def MyWin_Loaded(self, sender, e):
MessageBox.Show("Loadedイベントが発生")
def MyWin_ContentRendered(self, sender, e):
MessageBox.Show("ContentRenderedイベントが発生")
def MyWin_Closing(self, sender, e):
MessageBox.Show("Closingイベントが発生")
def MyWin_Deactivated(self, sender, e):
MessageBox.Show("Deactivatedイベントが発生")
def MyWin_Closed(self, sender, e):
MessageBox.Show("Closedイベントが発生")
def MyWin_Unloaded(self, sender, e):
MessageBox.Show("Unloadedイベントが発生")
if __name__ == '__main__':
Application().Run(MyWindow())
ActivatedイベントとDeactivatedイベントは、ユーザーがPCで実行されている複数のウィンドウを切り替えるたびに、
何度も発生します。実際にやってみると発生しまくってPCが操作できなくなってしまったので
コメントアウトしました。もし使っていたら、上記の順番で発生するだろうということで記載しています。
予想なので前に"?"を付けました。ちょっといい加減で m(_ _)m普通使うイベントは、Loaded、Closingの2つです。Loadedイベントでは、ウィンドウの初期状態を設定します。
Closingイベントは、ウィンドウが閉じる前に発生します。このイベントはキャンセルできるので、ユーザー確認の コードを書いて、ウィンドウが閉じるのをやめることができます。
例を下に書きました。Windowを表示すると、タイトルに起動した時間を表示します。またこのウィンドウを閉じようとすると メッセージボックスが開きます。[はい]を選択した場合のみ閉じます。
XAMLファイル(window3.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="window3" Height="300" Width="400"
Loaded = "MyWin_Loaded"
Closing = "MyWin_Closing" >
</Window>
スクリプトファイル
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import MessageBox, MessageBoxButtons, DialogResult
import wpf
from System.Windows import Application, Window
from System import DateTime
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'window3.xaml')
def MyWin_Loaded(self, sender, e):
MessageBox.Show("Loadedイベントが発生")
self.Title = "Loaded Time is " + DateTime.Now.ToString()
def MyWin_Closing(self, sender, e):
MessageBox.Show("Closingイベントが発生")
if MessageBox.Show("Windowを閉じてもいいですか?","Closing メッセージ",
MessageBoxButtons.YesNo) == DialogResult.No :
e.Cancel = True
if __name__ == '__main__':
Application().Run(MyWindow())
別のWindowを表示する
Windowを表示させるための方法はShow、ShowDialogメゾットと、Visibilityプロパティの設定です。Showメゾットと VisibilityプロパティをVisibleに設定することは、全く同じ結果が得られます。したがって、Showメゾットと ShowDialogメゾットという2種類の表示の仕方があります。2つの表示の仕方の違いは、モードを有するWindow (モーダルWindow)を表示するか、モードが無いWindow(モードレスWindow)を表示するかの違いです。そうすると、モードって何?って話になります。モードの英語の意味は"状態"です。"状態"を有する Windowとは、普通とは違った決まった"状態"にさせて、ユーザーの作業を制限させるWindowの意味です。 言葉で説明しようとすると難しいですが、具体的にはアプリケーションの他のWindowをブロックして、ユーザーが ちゃんと作業しないと次へ進めないWindowのことをモーダルWindowと呼び、その逆で他のWindowをブロックせず、 ユーザーは任意のWiindowを操作することができるWindowをモードレスWindowと呼びます。
ShowメゾットはモードレスWindowとして表示させ、ShowDialogメゾットはモーダルWindowとして表示させます。 例をみてみましょう。
XAMLファイル(window4.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="元のWindow" Height="115" Width="300">
<StackPanel>
<Button Click="MyWin_Show">Showメゾット</Button>
<Button Click="MyWin_Visible">Visiblity = Visible</Button>
<Button Click="MyWin_ShowDialog">ShowDialogメゾット</Button>
</StackPanel>
</Window>
スクリプトファイル
import wpf
from System.Windows import Application, Window, Visibility
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'window4.xaml')
def MyWin_Show(self, sender, e):
w = Window()
w.Title = "Showメゾットで表示しています"
w.Show()
def MyWin_ShowDialog(self, sender, e):
w = Window()
w.Title = "ShowDialogメゾットで表示しています"
w.ShowDialog()
def MyWin_Visible(self, sender, e):
w = Window()
w.Title = "Visibility = Visibleで表示しています"
w.Visibility = Visibility.Visible
if __name__ == '__main__':
Application().Run(MyWindow())

最初の2つのボタンをクリックするとWindowが表示されますが、タイトル以外は全く同じ結果が得られます。 また元のWindowを選択して任意の数のWindowを作成することが可能です。
それに対して、3番目のボタンをクリックした場合、元のWindowを選択することはできません。
Windowのオーナー
前の例でShowメゾットを使用した場合、元のWindowを閉じても新しくできたWindowは消えません。 これはアプリケーション内にWindowの優越がなく、すべてのWindowが平等のアプリケーションで、 Internet ExplorerみたいにすべてのWindowが閉じたときに初めてアプリケーションが終了するタイプに 適しています。それに対して、ExcelみたいにメインのWindowがあり、そのWindowがすべてWindowをコントロールし、 MainのWindowが閉じるとアプリケーションが終了するタイプのアプリケーションを作るときは、 新しいWindowを作る際に、オーナーを指定します。 例を作ってみました。
XAMLファイル(window5.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="オーナーウィンドウ" Height="100" Width="300">
<Grid>
<Button Click="MyWin_Show" FontSize="20">Child Windowを表示する</Button>
</Grid>
</Window>
スクリプトファイル
import wpf
from System.Windows import Application, Window
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'window5.xaml')
def MyWin_Show(self, sender, e):
w = Window()
w.Title = "Child Window"
w.Owner = self
w.Show()
if __name__ == '__main__':
Application().Run(MyWindow())
例では、Child Windowは常にオーナーWindowの前に表示されますが、モードレスWindowのように
オーナーWindowの選択を妨げません。またChild Windowは[Alt]+[Tab]キーを押したときに表示される
ウィンドウリストには表示されません。あとChild Windowの特徴として、オーナーWindowを閉じると自動的に閉じ、
オーナーWindowが最小化されると自動的に非表示になることなどが挙げられます。Windowの表示位置とサイズ
Windowの表示方法が説明したところで、Windowを画面のどこに表示するかやWindowサイズを制御する方法を説明していきます。Windowの位置を指定するにはWindowStartUpLocationプロパティとTopプロパティ、Leftプロパティを組み合わせて 行います。Windowの大きさは、SizeToContentプロパティとWidthプロパティ、Heightプロパティを組み合わせて指定します。
SizeToContentとは、Windowのサイズがコンテンツのサイズに合わせて自動的に調整されるかどうか設定するプロパティです。 SizeToContent を WidthAndHeight に設定すると、Height または Width の設定は無効になります。 SizeToContent が Height に設定されている場合は、Height の設定によってウィンドウの高さが変更されません。 SizeToContent が Width に設定されている場合は、Width の設定によってウィンドウの幅が変更されません。 Windowの位置と大きさを決定したあとで、ユーザーがWindowのサイズを変更できるかどうかを指定するのがResizeModeプロパティです。 また、MinWidth、MaxWidth、MinHeight、MaxHeightのプロパティは、読んで字のごとくユーザーが変更できるWindowのサイズの上下限を 指定することができます。
最後に、Windowの位置やサイズの現在の値は、Width、Height、Top、Leftの各プロパティにアクセスして知ることができます。 逆にこれらのプロパティに代入することで、いつでもWindowの位置やサイズを設定することもできます。
このあたりは、もう自然にやっている基本的なことでしょうか。さて、例をみてみましょう。
XAMLファイル(window6.xaml)
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ウィンドウを移動させる" Height="345" Width="318" ResizeMode="CanMinimize"
Loaded="MyWin_Loaded">
<StackPanel Margin="5" Orientation="Vertical">
<StackPanel Margin="0" Orientation="Horizontal">
<Button Width="100" Height ="100" Click="MyWin_TopLeft" FontSize="15">左上に移動</Button>
<Button Width="100" Height ="100" Click="MyWin_Top" FontSize="15">上に移動</Button>
<Button Width="100" Height ="100" Click="MyWin_TopRight" FontSize="15">右上に移動</Button>
</StackPanel>
<StackPanel Margin="0" Orientation="Horizontal">
<Button Width="100" Height ="100" Click="MyWin_Left" FontSize="15">左に移動</Button>
<Button Width="100" Height ="100" Click="MyWin_Size" FontSize="15">サイズ変更</Button>
<Button Width="100" Height ="100" Click="MyWin_Right" FontSize="15">右に移動</Button>
</StackPanel>
<StackPanel Margin="0" Orientation="Horizontal">
<Button Width="100" Height ="100" Click="MyWin_ButtomLeft" FontSize="15">左下に移動</Button>
<Button Width="100" Height ="100" Click="MyWin_Buttom" FontSize="15">下に移動</Button>
<Button Width="100" Height ="100" Click="MyWin_ButtomRight" FontSize="15">右下に移動</Button>
</StackPanel>
</StackPanel>
</Window>
スクリプトファイル
import wpf
from System.Windows import Application, Window, WindowStartupLocation
class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'window6.xaml')
def MyWin_Loaded(self, sender, e):
self.w = Window()
self.w.Width = 200
self.w.Height = 200
self.w.Title = "Child Window"
self.w.WindowStartupLocation = WindowStartupLocation.CenterScreen
self.w.Owner = self
self.w.Show()
def MyWin_TopLeft(self, sender, e):
self.w.Top -= 20
self.w.Left -= 20
def MyWin_Top(self, sender, e):
self.w.Top -= 20
def MyWin_TopRight(self, sender, e):
self.w.Top -= 20
self.w.Left += 20
def MyWin_ButtomLeft(self, sender, e):
self.w.Top += 20
self.w.Left -= 20
def MyWin_Buttom(self, sender, e):
self.w.Top += 20
def MyWin_ButtomRight(self, sender, e):
self.w.Top += 20
self.w.Left += 20
def MyWin_Left(self, sender, e):
self.w.Left -= 20
def MyWin_Right(self, sender, e):
self.w.Left += 20
def MyWin_Size(self, sender, e):
if self.w.Width > 300 :
self.w.Top += 60
self.w.Left += 60
self.w.Width -= 120
self.w.Height -= 120
else:
self.w.Top -= 20
self.w.Left -= 20
self.w.Width += 40
self.w.Height += 40
if __name__ == '__main__':
Application().Run(MyWindow())

完全にフライングですが、"StackPanel"はレイアウト要素として別で説明します。
最後は遊びですね。済みません(^^;。これだけ遊べば、XAMLでWindowを作ることに慣れてきてもらえたのでは ないでしょうか。
※Silverlightを使ってWindowを表示するところを再現しようとしましたが、セキュリティの関係でブラウザでSiverlightを 使った場合、Windowインスタンスが作成できませんでした。ごめんなさい。次の要素からはSilverlightでも作成できるので 実際にWebでも、実際にサンプルを実行させたような画面を表示させていきます。