2008/2/10 Sun

WPFのListViewのGrid表示モードでの右寄せとか

Filed under: プログラム — nico @ 2:18:39

WPFっつーか、XAMLはひっじょーに強力なUIデザインツールなんですが、残念ながらやっぱり完全とゆーワケでもなく、時に泥臭い対応しないとダメな時もあるようで、そのお話。

WPFのコントロールの中でも、かなり強力な部類に入るListViewコントーロールですが、ところどころ歯抜けの様に欠点があるわけです。
カラム定義をテンプレートに出来ないとか(GridView.Columnsな)、時々痒い所に手が届かない訳ですが、その中でも最高に困ったのが、
「セルのテキストのセンタリングや右寄せが出来ない」
という動作。

GridViewColumn自体にその設定がないだけではなく、CellTemplate使っても出来ないんですよ、これが。

XAML
<DataTemplate x:Key="myColumn">
  <TextBlock HorizontalAlignment="Stretch"
                 TextAlignment="Right" .../>

</DataTemplate>
...
<GridViewColumn
    CellTemplate="{StaticResource myColumn}" ... />

とかやっても、TextBlockの横幅はセルの幅に合わせて広がらないので、右寄せ設定は生きててもテキストはセルの左端に表示されたり。
TextBlockの親にGridとかStackPanel等の配置用コンテナを挿入しても、そのコンテナも同様にWidthがテキストの横幅で自動計算されてしまい、やっぱり不可。

TextBlockなりにWidthを指定してしまえば、そのWidthの範囲内では右寄せされるけど、ヘッダの幅を変えてしまうとダメになってしまうちょっと悲しい状況に。
結局どーすれば良いのかというと、TextBlockのサイズをヘッダの幅に合わせて変更するしかない。

XAMLだけで対処しようとすると、今のところこんな感じの対処しか思いつかなかった・・・orz

XAML
<Style x:Key="stretchWidth">
  <Setter Property="Width">
    <Setter.Value>
      <Binding Path="Columns[0].ActualWidth">
        <Binding.RelativeSource>
          <RelativeSource
              Mode="FindAncestor"
              AncestorType="{x:Type GridViewRowPresenter}"
          />

        </Binding.RelativeSource>
      </Binding>
    </Setter.Value>
  </Setter>
  <Setter Property="Margin" Value="-5 0 -5 0"/>
  <Setter Property="Padding" Value="5 0 5 0"/>
</Style>
<DataTemplate x:Key="sizePaneTamplate">
  <TextBlock Style="{StaticResource myColumn}"
                  Margin="-5 0 -5 0"
                  padding="5 0 5 0"/>

</DataTemplate>

まぁ、何をしているのかといえば、RelativeSourceで先祖にあるGridViewRowPresenterクラスを探し出して、そのColumnsコレクションの「表示してるカラムの」ActualWidthをTextBlockのWidthにバインディング。

非常に泥臭くてイヤラシイ事に、スタイル&テンプレート&バインディング利用してるくせに、カラムの取得に固定値のIndexが必要だったり。
さらにはVisualTreeでListViewの行コンテナであるGridViewRowPresenterとTextBlockの間に入るContentPresenterにMarginが設定されてるせいで、そのままでは切れるので回避するためにマイナスMarginとそれを打ち消すPaddingをやっぱり固定で設定してたりとか。
ぶっちゃけ、テーマ変わるとズレますよ、これ。

まぁ、XAMLオンリーに拘らずC#とか使えばもーちょいマシな対処もできるし俺的にはそっちの方が好みだけど、とりあえず今回はXAMLオンリーでも出来るしどっかで要望あるかもしれないって事で。
ってゆーか、XAMLオンリーでもっとマシな解決策あるなら誰かおせーてw

(2/19 追記)
通りすがりさん情報でもっと楽にできる事が判明。
詳しくはこちらへ。

コメント (5) »

  1. ListViewItem.HorizontalContentAlignment でセル(コンテンツ)の幅や位置を設定できますよ。

    コメント by 通りすがり — 2008/2/19 Tue @ 5:39:41

  2. あらら、サンプルコードが削除されて「…」だけに。

    コメント by 通りすがり — 2008/2/19 Tue @ 5:53:04

  3. >あらら、サンプルコードが

    ぬあぁ、すいません、なんかコメント欄に不明タグ入ってくると削除しちゃうみたいですね。
    管理者画面でも見れなかったので、登録時に弾かれるっぽいです・・・orz

    ListViewItem.HorizontalContentAlignmentですが、起き抜けに試したら出来たので、後でまとめて記事起こそうと思います。
    ありがとうございました。

    コメント by nico — 2008/2/19 Tue @ 9:47:17

  4. XAMLだけでやる場合は

    の箇所で width を広げてやると良いみたいです。

    TextBlock の幅が自動調整されているようなので、
    TextBlock の配置が左寄せの場合、テキスト配置が右寄せになっても
    視覚的に変化しないようです。

    見当違いなこといってたらスミマセン;

    コメント by ゲスト — 2009/8/9 Sun @ 13:50:28

  5. タグ削除されました・・・

     >「の箇所で~」

    DataTemplate の TextBlock 内をさしています。

    コメント by ゲスト — 2009/8/9 Sun @ 13:51:47

コメント RSS トラックバック URL

コメントをどうぞ

Link Free. Copyright (C) 2005-2007 nico. All rights reserved.
HTML convert time: 0.794 sec. Powered by WordPress ME