トグルボタンでDataGridのRowDetailを表示する
2015年3月16日
2022年2月3日
トグルボタンで行が開いたり閉じたりするやつ。
RowDetailsTemplateを書いて、コンバータで閉じたり開いたりする。
ググって最初にでてきた「How to toggle RowDetails on a WPF DataGrid」を参考にした。
以前仕事でやってたのはCodeProjectの何かだったけど見つからなかった。
以下、手順のメモ。
最近作ってる「イベントログからPCの稼働時間を取得するアプリ」で1日分のEventLogは複数あるので、それをDetailで表示する。
1日分のDetail用のコントロールを作って、
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 29 30 31 32 33 |
<UserControl x:Class="PCTime.View.EventDetailControl" 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" Height="Auto" Width="306"> <UserControl.Resources> <DataTemplate x:Key="EventDetailItemsControl"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <TextBlock Text="{Binding StartTime, StringFormat=HH:mm:ss}" TextAlignment="Center" FontSize="14"/> <TextBlock Text="{Binding EndTime, StringFormat=HH:mm:ss}" Grid.Column="1" TextAlignment="Center" FontSize="14"/> </Grid> </DataTemplate> </UserControl.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="16"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="10"/> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Content="開始" Grid.Column="1" Padding="0,0,0,0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="14"/> <Label Content="終了" Grid.Column="2" Padding="0,0,0,0" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" FontSize="14"/> <ItemsControl Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" ItemsSource="{Binding DateList}" ItemTemplate="{StaticResource EventDetailItemsControl}"/> </Grid> </UserControl> |
こんなクラスのコレクションにバインドするようにする。
1 2 3 4 5 6 7 8 |
: public List<DateData> DateList { get; set; } // 日付における開始・終了時刻のペアのリスト public class DateData { public DateTime? StartTime { get; set; } public DateTime? EndTime { get; set; } } : |
これを、DataGridのRowDetailsTemplateに指定する。
1 2 3 4 5 6 7 |
<DataGrid.RowDetailsTemplate> <DataTemplate> <Grid Background="LightGray"> <local:EventDetailControl /> </Grid> </DataTemplate> </DataGrid.RowDetailsTemplate> |
DataGridの最初の列はトグルボタンにして、 参考ソースのテンプレートを指定する。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<DataGrid.Resources> <DataTemplate x:Key="ExpandDetails"> <ToggleButton Name="ShowDetails" IsChecked="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=DetailsVisibility, Converter={StaticResource VisivilityToBooleanConv}, Mode=TwoWay}" Margin="0,0,0,0" Style="{StaticResource ToggleButtonStyle1}"/> </DataTemplate> </DataGrid.Resources> <DataGrid.Columns> <DataGridTemplateColumn Header="" CellTemplate="{StaticResource ExpandDetails}" Width="30"> </DataGridTemplateColumn> |
開いたり閉じたりするコンバーターは、Visibility⇔Booleanを変換するやつを作成。
サンプルのやつだとエラー出てうまく動かなかった。属性は苦手・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
class VisivilityToBooleanConverter : IValueConverter { /// <summary> /// Detailの表示/非表示 /// </summary> /// <param name="value"></param> /// <param name="targetType"></param> /// <param name="parameter"></param> /// <param name="culture"></param> /// <returns></returns> public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (Visibility)value == Visibility.Visible; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return (bool)value ? Visibility.Visible : Visibility.Collapsed; } } |
DataGridが行選択モードだとチカチカするのでセル選択モードに、
1 2 3 4 |
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding DateTimeDatas}" FontSize="16" Grid.Row="5" Grid.ColumnSpan="6" CanUserSortColumns="True" CanUserAddRows="False" CanUserDeleteRows="False" IsReadOnly="True" SelectionMode="Single" SelectionUnit="Cell" Grid.Column="1" > |
トグルボタンのスタイル。(画像はフリー素材を適当に物色)
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <!-- Detail表示ボタン --> <Style x:Key="ToggleButtonStyle1" TargetType="{x:Type ToggleButton}"> <Setter Property="Width" Value="16"/> <Setter Property="Height" Value="16"/> <Setter Property="Foreground" Value="White"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ToggleButton"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver"/> <VisualState x:Name="Pressed"/> <VisualState x:Name="Disabled"/> </VisualStateGroup> <VisualStateGroup x:Name="CheckStates"> <VisualState x:Name="Checked"> <Storyboard> <ObjectAnimationUsingKeyFrames BeginTime="0:0:0" Storyboard.TargetName="border" Storyboard.TargetProperty="(Border.Background)" > <DiscreteObjectKeyFrame KeyTime="00:00:00"> <DiscreteObjectKeyFrame.Value> <ImageBrush ImageSource="/PCTime;component/View/Images/sita.png"> </ImageBrush> </DiscreteObjectKeyFrame.Value> </DiscreteObjectKeyFrame> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Unchecked"/> </VisualStateGroup> <VisualStateGroup x:Name="FocusStates"> <VisualState x:Name="Focused"/> <VisualState x:Name="Unfocused" /> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Border Name="border" BorderThickness="0" BorderBrush="Transparent"> <Border.Background> <ImageBrush ImageSource="/PCTime;component/View/Images/migi.png" /> </Border.Background> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> <ContentPresenter x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/> <Rectangle x:Name="DisabledVisualElement" RadiusX="3" RadiusY="3" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" /> <Rectangle x:Name="FocusVisualElement" RadiusX="2" RadiusY="2" Margin="1" Stroke="#FF6DBDD1" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> |