WPF TreeViewのアイテムを幅一杯に伸ばす

blog20130222-StretchTreeViewItem

TreeViewLink の各アイテムを枠囲みしたり背景を色付にしようとすると、内部のテキストをぴったり納めるような枠のサイズになってデコボコしたりLink中身のサイズを固定するとサブアイテムのお尻が右に飛び出るLink といまいち綺麗じゃありません。

TreeView.HorizontalContentAlignment=Stretchで解決できると思いきや、TreeViewはこのプロパティを華麗に無視。TreeViewItemのテンプレートを根こそぎ変更しないといけないらしい。1から書くと大変そうなのでネットにあったテンプレートLink を改造。変更点は、

  • テンプレートの最初にあるGridがTreeViewItemを表示する部分。HorizontalAlignment="Stretch"にして目一杯横に広がるようにする。
  • そのGridの2カラム目が肝心の中身。ここのWidthをAutoから*に。
  • 3カラム目は要らない子なので削除。
  • 消した3カラム目の辻褄合わせに、下のほうにあるItemsPresenterのColumnSpan指定を削除。
<UserControl x:Class="TreeViewTest"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300">

    <UserControl.Resources>
        <Style TargetType="TreeViewItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TreeViewItem" xmlns:s="clr-namespace:System;assembly=mscorlib">
                        <Grid HorizontalAlignment="Stretch">
                        <!--
                        <Grid>
                        -->
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto" MinWidth="19" />
                                <ColumnDefinition Width="*"/>
                                <!-- Change to expand width of tree items to base TreeView size (expand to right edge)
                                <ColumnDefinition Width="Auto" />
                                <ColumnDefinition Width="*" />
                                -->
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition />
                            </Grid.RowDefinitions>
                            <ToggleButton IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent},Path=IsExpanded,Mode=TwoWay}" ClickMode="Press" Name="Expander">
                                <ToggleButton.Style>
                                    <Style TargetType="ToggleButton">
                                        <Style.Resources>
                                            <ResourceDictionary />
                                        </Style.Resources>
                                        <Setter Property="UIElement.Focusable">
                                            <Setter.Value>
                                                <s:Boolean>False</s:Boolean>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="FrameworkElement.Width">
                                            <Setter.Value>
                                                <s:Double>16</s:Double>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="FrameworkElement.Height">
                                            <Setter.Value>
                                                <s:Double>16</s:Double>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="Control.Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="ToggleButton">
                                                    <Border Padding="5,5,5,5" Background="#00FFFFFF" Width="30" Height="30">
                                                        <Path Fill="#00FFFFFF" Stroke="#FF989898" Name="ExpandPath">
                                                            <Path.Data>
                                                                <!--※②マークを変えるにはここの値を変える-->
                                                                <PathGeometry Figures="M0,0L0,10L10,0z" />
                                                            </Path.Data>
                                                            <Path.RenderTransform>
                                                                <RotateTransform Angle="135" CenterX="3" CenterY="3" />
                                                            </Path.RenderTransform>
                                                        </Path>
                                                    </Border>
                                                    <ControlTemplate.Triggers>
                                                        <Trigger Property="UIElement.IsMouseOver">
                                                            <Setter TargetName="ExpandPath" Property="Shape.Stroke">
                                                                <Setter.Value>
                                                                    <SolidColorBrush>#FF1BBBFA</SolidColorBrush>
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Setter TargetName="ExpandPath" Property="Shape.Fill">
                                                                <Setter.Value>
                                                                    <SolidColorBrush>#00FFFFFF</SolidColorBrush>
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Trigger.Value>
                                                                <s:Boolean>True</s:Boolean>
                                                            </Trigger.Value>
                                                        </Trigger>
                                                        <Trigger Property="ToggleButton.IsChecked">
                                                            <Setter TargetName="ExpandPath" Property="UIElement.RenderTransform">
                                                                <Setter.Value>
                                                                    <RotateTransform Angle="180" CenterX="3" CenterY="3" />
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Setter TargetName="ExpandPath" Property="Shape.Fill">
                                                                <Setter.Value>
                                                                    <SolidColorBrush>#FF595959</SolidColorBrush>
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Setter TargetName="ExpandPath" Property="Shape.Stroke">
                                                                <Setter.Value>
                                                                    <SolidColorBrush>#FF262626</SolidColorBrush>
                                                                </Setter.Value>
                                                            </Setter>
                                                            <Trigger.Value>
                                                                <s:Boolean>True</s:Boolean>
                                                            </Trigger.Value>
                                                        </Trigger>
                                                    </ControlTemplate.Triggers>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </ToggleButton.Style>
                            </ToggleButton>
                            <Border BorderThickness="{TemplateBinding Border.BorderThickness}" Padding="{TemplateBinding Control.Padding}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="Bd" SnapsToDevicePixels="True" Grid.Column="1">
                                <ContentPresenter Content="{TemplateBinding HeaderedContentControl.Header}" ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}" ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}" ContentSource="Header" Name="PART_Header" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
                            </Border>
                            <!--
                            <ItemsPresenter Name="ItemsHost" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2"/>
                            -->
                            <ItemsPresenter Name="ItemsHost" Grid.Column="1" Grid.Row="1"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="TreeViewItem.IsExpanded">
                                <Setter TargetName="ItemsHost" Property="UIElement.Visibility" Value="{x:Static Visibility.Collapsed}" />
                                <Trigger.Value>
                                    <s:Boolean>False</s:Boolean>
                                </Trigger.Value>
                            </Trigger>
                            <Trigger Property="ItemsControl.HasItems">
                                <Setter TargetName="Expander" Property="UIElement.Visibility" Value="{x:Static Visibility.Hidden}" />
                                <Trigger.Value>
                                    <s:Boolean>False</s:Boolean>
                                </Trigger.Value>
                            </Trigger>
                            <Trigger Property="TreeViewItem.IsSelected">
                                <Setter TargetName="Bd" Property="Panel.Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                                <Setter Property="TextElement.Foreground">
                                    <Setter.Value>
                                        <DynamicResource ResourceKey="{x:Static SystemColors.HighlightTextBrushKey}" />
                                    </Setter.Value>
                                </Setter>
                                <Trigger.Value>
                                    <s:Boolean>True</s:Boolean>
                                </Trigger.Value>
                            </Trigger>
                            <MultiTrigger>
                                <MultiTrigger.Conditions>
                                    <Condition Property="TreeViewItem.IsSelected">
                                        <Condition.Value>
                                            <s:Boolean>True</s:Boolean>
                                        </Condition.Value>
                                    </Condition>
                                    <Condition Property="Selector.IsSelectionActive">
                                        <Condition.Value>
                                            <s:Boolean>False</s:Boolean>
                                        </Condition.Value>
                                    </Condition>
                                </MultiTrigger.Conditions>
                                <Setter TargetName="Bd" Property="Panel.Background" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
                                <Setter Property="TextElement.Foreground">
                                    <Setter.Value>
                                        <DynamicResource ResourceKey="{x:Static SystemColors.ControlTextBrushKey}" />
                                    </Setter.Value>
                                </Setter>
                            </MultiTrigger>
                            <Trigger Property="UIElement.IsEnabled">
                                <Setter Property="TextElement.Foreground">
                                    <Setter.Value>
                                        <DynamicResource ResourceKey="{x:Static SystemColors.GrayTextBrushKey}" />
                                    </Setter.Value>
                                </Setter>
                                <Trigger.Value>
                                    <s:Boolean>False</s:Boolean>
                                </Trigger.Value>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <Setter Property="ItemsPanel">
                <Setter.Value>
                    <ItemsPanelTemplate>
                        <!--※①マージンを変える場合はここ-->
                        <StackPanel IsItemsHost="True" Margin="20,0,0,0"/>
                    </ItemsPanelTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>

    <TreeView Name="tree" ItemsSource="{Binding Items}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate DataType="{x:Type TVItem}" ItemsSource="{Binding Items}">
                <Border BorderBrush="Silver" BorderThickness="2" Margin="0.5" Padding="2">
                    <Grid HorizontalAlignment="Stretch">
                        <Grid.RowDefinitions>
                            <RowDefinition MinHeight="32"/>
                            <RowDefinition MinHeight="20"/>
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="200"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>
                        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Content="{Binding Name}" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Center" />
                        <Label Grid.Row="1" Grid.Column="0" Content="{Binding Status}" FontSize="16" HorizontalAlignment="Left" VerticalAlignment="Center"/>
                        <ProgressBar Grid.Row="1" Grid.Column="1" Minimum="0" Maximum="1" Value="{Binding Progress}" HorizontalAlignment="Stretch"/>
                    </Grid>
                </Border>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>
</UserControl>
元データとなるCLRクラスはこんな感じです。
public partial class TreeViewTest : UserControl
{
    public TreeViewTest()
    {
        InitializeComponent();

        DataContext = new
        {
            Items = new TVItem[]
            {
                new TVItem()
                {
                     Name = "Item 1",
                     Status = "Status 1",
                     Progress = 0.1
                },
                new TVItem()
                {
                    Name = "Item 2",
                    Status = "Status 2",
                    Progress = 0.3,
                    Items = new TVItem[]
                    {
                        new TVItem()
                        {
                            Name = "Item 2-1",
                            Status = "Status 2-1",
                            Progress = 0.5
                        },
                        new TVItem()
                        {
                            Name = "Item 2-2",
                            Status = "Status 2-2",
                            Progress = 0.7
                        }
                    }
                }
            }
        };
    }
}

public class TVItem
{
    public string Name { get; set; }
    public string Status { get; set; }
    public double Progress { get; set; }
    public IEnumerable<TVItem> Items{ get; set; }
}

[参考]

[2013/02/24] コード修正

— posted by mu at 07:03 pm  

PlayStation4発表

発表の動画配信を視聴中。

動画が何回か途切れたので取りこぼした情報がありそうですが、オンライン配信とSNSに向かうのか。発表されたマシンの性能・サービスがPCやハイエンドタブレットでではできないレベルとは感じられず、勝負はマシン性能ではなくオンラインサーバーを含めたサービス環境が魅力的かどうかなんだろうな。というのは当たり前の事でして、昔からマシン性能を高らかに謳うゲーム機は負ける率が高いのですが。

でPS4-PSVita-ソニエリ製携帯による囲い込みを狙う。Vitaは事実上PS4の別売りリモート端末扱い→携帯が高機能化してお役御免という道かなぁ。

[2013/2/21 少々修正]

— posted by mu at 09:01 am  

DD-WRTでNTPサーバー

1 of 41234Next»
早くも先日購入したRTX-1000Link は引退の方向。理由はVPN機能でして、RTX-1000が提供している2つのVPNは
  • PPTP: 解読されてしまってるLink 。現時点解析に必要なマシンがそれほど安くないので、個人使用のVPNを解読されるリスクを気にしないなら使えますが。
  • IPSec: 通信するマシンのどちらかがグローバル固定IPが必要とのこと。やりたいのは出先からDDNSで運用している自宅への接続なのでこれもダメ。

授業料は安かったとはいえ、もうちょっと事前に調べておけばよかった。次の案として出てきたのがDD-WRTLink 。これは市販の安価なブロードバンドルーターにもよく使われているファームウェアですが、市販品はブラウザを介して限定した機能しかユーザーに変更を許してないため、ファームウェアを書き換えて隠された設定も表に出すというもの。

OpenVPN機能を使うとなるとファームウェアのサイズが大きくなってしまうため、それを格納できるフラッシュメモリ容量が必要になります。となると機種が一挙に限定されまして、Buffalo WZR-HP-G300NH/301NHLink ぐらいでしょうか、入手しやすいのは。

暗号キーをブラウザ経由で設定するというのがなんとも違和感ありますが、OpenVPNも動くようです。となると欲が出て来まして、自宅向けNTPサーバーもこいつに担わせたい。が、これが結構大変。

  • DD-WRT標準のntpd: 返事がない。ただのクライアントのようだ。どうやら自機(ルーター)の内蔵時計を合わせるためだけにあり、サーバー機能を有効にする方法がわからず。
  • いわゆるフル機能ntpd: 実行直後にSegmentation faultが出て落ちる。
  • busybox ntpd: クライアントからの問い合わせが、前回から時間が経っていると失敗することが多い。
  • openntpd: 上位サーバーを選ぶ

次ページより、busybox ntpdとopenntpdの備忘録。

1 of 41234Next»

— posted by mu at 11:13 am   commentComment [0]  pingTrackBack [0]

この国では成長途中のOOM Killerのことを

blog20130212-ArticleOOMKiller

ロボットによるアクセス数をカウントしないLink ということをやっているため、アクセスカウンタのチェックは時々やってます。今日見るといつもの倍に増加。どこのロボットだと思ったらOOM Killerの記事Link/.Link にリンクされていましたか。

これまで当ブログではSQL ServerへService Packを当てるLink 記事が圧倒的なアクセス数を記録していたのですが、こちらの問題は収束したようで最近アクセスは激減。一方OOM Killerは依然として悩みの種なのか相変わらず読まれているようで累計アクセス数がトップになるのは時間の問題でしょう。

久々にOOM Killerの記事を読み返して思ったのは、この頃は砕けた口調で書けてたんだなということと、こんなに頻繁に書いていたんだということ。2日に1回のペースなんて今じゃ信じられない。最近書くネタなくてねぇ(泣)

あ、タイトルはリンク元の/.のコメントでOOM Killerをまどマギにかけていたので、それにちなんでみただけです。

— posted by mu at 11:53 pm   commentComment [0]  pingTrackBack [0]

プロバイダ乗り換え手続き開始

今のインターネットプロバイダとは11年半契約していたらしい。月額1980円のADSL 12M。個人的にはこの速度で十分で、安定している。光やケーブルテレビの勧誘が来てもこの値段になったら考えると言えば、まぁ諦めてくれます。

今回乗り換える先はイー・アクセスのADSL-directLink 。同じ12Mで月額が1480円と500円削減。1年で6000円、10年で60000円と考えると手間を惜しまず乗り換える気に。これでますます光の勧誘が断りやすくなる(^_^;)

ただし裏がありまして、メールや個人ウェブページなどの付随サービスが一切ありません。メールはGMailなど無料メールを使えってこと。私の場合は現時点このブログをホスティングしているさくらのレンタルサーバLink がメールも個人ページもストレージも提供してくれるわけでそこに障害は無し。

実は今使っているプロバイダも家から局まではイー・アクセスのADSLを利用しているわけでして、おそらくモデムの交換は不要。ひょっとしたら回線工事も実質不要で、PPPoEのIDとパスワードさえ発行されればモデムの設定変更だけで切り替わっちゃうんじゃないかと。フレッツLink がまさにそういうものでして、同時に複数のプロバイダと契約してもモデムの設定変更で切替できちゃうらしいです。

結論を言うと先日イー・アクセスから通知が来まして、ここのADSLは複数のプロバイダを併用することは不可、今のプロバイダを解約した後じゃないとADSL-directは開通できないとのこと。ただ乗り換えのサポートはできるだけやってくれるようで、ADSL-direct申し込み→今のプロバイダ解約してねと手紙が来る→解約したとの連絡不要、移行日の調整含め後は任せろ、って流れのようです。

— posted by mu at 01:01 am  

T: Y: ALL: Online:
ThemeSwitch
  • Basic
Created in 0.0164 sec.
prev
2013.2
next
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28