Ktouth Brand. on Web

け〜くんこと K.Ktouth のだらだらした日常と突発的に作るプログラムや読み物とかの雑多サイト



[2007年12月04日]

XAMLでツールバーのボタンの無効への切り替え

2007年12月06日 10:38更新 筆者:K.Ktouth

Wiiフィット (「バランスWiiボード」同梱)(AA)

昨日はWiiFitやり過ぎて片足だけ筋肉痛。どんだけバランス悪いんよ俺……わーん
でも一応は1時間プレイして0.5kg減。順調に減ってますね〜♪
あ、それに時間取りすぎたので書く事ありません(ぉぃ

と、さすがにそれではアレなので続きにXAMLの小技でも。

ツールバーのボタンを無効化する

WPFアプリではXAMLでUIを定義し、コードからは極力切り離すような設計を行うようになっています。
肝心のデータはバインディングを駆使し、それによるUIの変化はTemplateやStyleを使って表現。アクションはCommand連結で。
慣れてくるとかなり楽しいです(笑)

で、ちょっと悩んだのがツールバーに配置したボタンのOn/Off。
仕様は以下の通り。

  • ContentControlの内部にツールバーがあり、その中のボタン(のいくつか)が対象。
  • ContentControlにはデータリストがソースとして連結されている。
  • 同じデータリストをソースとして連結しているリストボックスがある。
  • ツールバーは、そのリストボックスで選ばれている(もしくは未選択状態)一つのデータに対する操作を受け持つ。
  • ボタンにはCommandが連結され、そのコマンドに対象となるデータを渡す。

つまりツールバーにはリストボックスに表示されたデータの「新規作成」「編集」「削除」の基本操作ボタンが割り当てられているわけです。
新規作成はいつでも可能ですが、編集・削除に関しては当然、対象となるデータが必要になります。
WPFのリストボックスはフォーカスを失っても選択状態を失わないので、切り替え不要のように見えますが、データがない場合もありますし、選択状態をなくす方法はいくらでもあるので、きちんと切り分けておく必要があります。

んで、各項目の説明。
バインドなどの詳細は「方法 : コレクションにバインドして選択に基づく情報を表示する」を参照してください。

1:バインド用のアダプタを作成する

リストボックスやContentControlが受け取るデータリスト、それを取得するためのアダプタクラスを作成。

class ExampleListProvider {
 ObservableCollection<Example> GetList() { ... } // データのリストを返すC#コード
}

<Window.Resources>
 <ObjectProvider x:Key="ExampleList" ObjectType="{x:Type l:ExampleListProvider}" MethodName="GetList" />
</Window.Resources>

2:リストボックスとContentControlにリストを連結する

<ListBox Name="ExampleListBox" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource ExampleList}}" />
<ContentControl Content="{Binding Source={StaticResource ExampleList}}">
 <ToolBar>
  <Button Command="ApplicationCommands.New">新規作成</Button>
  <Button Command="ApplicationCommands.Edit">編集</Button>
  <Button Command="ApplicationCommands.Delete">削除</Button>
 </ToolBar>
</ContentControl>

3:ボタンにコマンドとデータを割り当てる

  <Button Command="ApplicationCommands.Edit" CommandParameter="{Binding}">編集</Button>
  <Button Command="ApplicationCommands.Delete"> CommandParameter="{Binding}">削除</Button>

コレで連結可能になるものの、連結されたデータがnullだと予期せぬエラーが出る。

4:Styleを使ってボタンの無効化を行う

<Window.Resources>
 <Style x:Key="ToolBarButton" TargetType="Button">
  <Style.Triggers>
   <Trigger Property="CommandParameter" Value="{x:Null}">
    <Setter Property="IsEnabled" Value="False" />
    <Setter Property="Opacity" Value="0.5" />
   </Trigger>
  </Style.Triggers>
  <Setter Property="IsEnabled" Value="True" />
  <Setter Property="Opacity" Value="1" />
 </Style>
</Window.Resources>

  <Button Command="ApplicationCommands.Edit" CommandParameter={Binding}" Style="{StaticResource ToolBarButton}">編集</Button>
  <Button Command="ApplicationCommands.Delete"> CommandParameter="{Binding}" Style="{StaticResource ToolBarButton}">削除</Button>

通常は有効・不透明とし、CommandParameterにnullが入っているときのみ無効・半透明化する。

ToDo

リスト(の親コントロール)からフォーカスが外れた際にリストの選択状態を解除する手法がよくわからない。
現状では対象となるコントロールにLostFocusイベントハンドラを指定、その中で ExampleListBox.SelectedValue = null; と指定している。
XAMLでイベントハンドラトリガーを利用すればうまく行きそうだが……?

本日のリンク元
アンテナ
その他のリンク元
検索