WPF ListBox и DataTemplates - В чем их сила и как избавиться от стандартного синего маркера выделения?
В очередной раз получил данный вопрос и решил поделиться ответом со всеми.
Как я думаю, многие знают, DataTemplates являются мощнейшим механизмом, позволяющим переопределять визуализацию элементов управления, выводящих множество элементов данных (ListBox, ListView, TreeView...).
С помощью них вы можете выводить в рамках одного визуального шаблона сразу множество аттибутов элемента данных.
Например, имея данный ListBox:
Я могу применив данный DataTemplate
1: <DataTemplate x:Key="EquityTemplate">
2: <Grid>
3: <Rectangle Margin="2" >
4: <Rectangle.Fill>
5: <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
6: <LinearGradientBrush.GradientStops>
7: <GradientStopCollection>
8: <GradientStop Color="#aaffffff" Offset="0"/>
9: <GradientStop Color="transparent" Offset="1"/>
10: </GradientStopCollection>
11: </LinearGradientBrush.GradientStops>
12: </LinearGradientBrush>
13: </Rectangle.Fill>
14: </Rectangle>
15: <Grid x:Name="StackPanel1" Height="29.1333333333334" Margin="5" >
16: <Grid.ColumnDefinitions>
17: <ColumnDefinition Width="40"/>
18: <ColumnDefinition Width="80"/>
19: <ColumnDefinition Width="80"/>
20: <ColumnDefinition Width="160"/>
21:
22: </Grid.ColumnDefinitions>
23: <TextBlock FontFamily="Segoe UI" x:Name="TextBlock1" Grid.Column="1" Width="Auto" Text="{Binding Mode=OneWay, Path=FirstName}" Margin="-0.5,0,15.5,12.4666666666666" FontSize="12" FontWeight="Bold" VerticalAlignment="Stretch" Height="Auto"/>
24: <TextBlock FontFamily="Segoe UI" Margin="0,0,0,0" Width="Auto" Height="16.6666666666668" Grid.Column="1" Grid.ColumnSpan="1" x:Name="TextBlock1_Copy" Text="{Binding Mode=OneWay, Path=LastName}" d:LayoutOverrides="GridBox" FontSize="10" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" TextTrimming="WordEllipsis"/>
25: <TextBlock FontFamily="Segoe UI" x:Name="TextBlock2" Grid.Column="2" Width="60" Text="{Binding Path=City, Mode=OneWay}" d:LayoutOverrides="None" FontSize="10" VerticalAlignment="Stretch" Margin="8.005,0,11.995,14.466" Height="Auto" Grid.ColumnSpan="1"/>
26: <TextBlock FontFamily="Segoe UI" d:LayoutOverrides="None" FontSize="10" FontWeight="Bold" VerticalAlignment="Stretch" Margin="0,14.401,0,0.065" Width="60" Height="Auto" Grid.Column="2" Grid.ColumnSpan="1" x:Name="TextBlock2_Copy" Text="{Binding Mode=OneWay, Path=Region}" HorizontalAlignment="Center" Background="{x:Null}"/>
27: <TextBlock FontFamily="Segoe UI" x:Name="TextBlock" Grid.Column="3" Text="{Binding Mode=OneWay, Path=OrdersCount}" FontSize="10" TextAlignment="Left" FontStyle="Normal" FontWeight="Bold" VerticalAlignment="Bottom" Margin="18.4,0,0,-0.001" Height="15.667" HorizontalAlignment="Stretch"/>
28: <TextBlock Margin="18.4,-2.16,-15.8,14.466" Text="{Binding Mode=OneWay, Path=Address}" TextWrapping="NoWrap" Grid.Column="3" VerticalAlignment="Stretch"/>
29:
30: <Image Margin="0,0,10,0" Source="{Binding Path=Photo}" Grid.Column="0" x:Name="image11" Stretch="Fill" Height="29" Width="27" />
31: </Grid>
32: </Grid>
33: </DataTemplate>
превратить его в
или применив данный DataTemplate
1: <DataTemplate x:Key="EquityTemplate">
2: <Viewbox>
3: <Grid>
4: <Image Source="{Binding Path=Photo}"></Image>
5: <Grid VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Height="60" >
6: <Rectangle Margin="0" >
7: <Rectangle.Fill>
8: <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
9: <LinearGradientBrush.GradientStops>
10: <GradientStopCollection>
11: <GradientStop Color="#55000000" Offset="0.001"/>
12: <GradientStop Color="#FF000000" Offset="1"/>
13: <GradientStop Color="#96000000" Offset="0.369"/>
14: </GradientStopCollection>
15: </LinearGradientBrush.GradientStops>
16: </LinearGradientBrush>
17: </Rectangle.Fill>
18: </Rectangle>
19: <StackPanel Orientation="Vertical">
20: <TextBlock FontWeight="Bold" FontFamily="Segoe UI" Foreground="#FF80A8FE" x:Name="TextBlock1" Width="Auto" Text="{Binding Mode=OneWay, Path=FirstName}" FontSize="20" VerticalAlignment="Stretch" Height="Auto"/>
21: <TextBlock FontWeight="Bold" FontFamily="Segoe UI" Margin="0,5,0,0" Foreground="#FF80A8FE" Width="Auto" Height="Auto" x:Name="TextBlock1_Copy" Text="{Binding Mode=OneWay, Path=LastName}" d:LayoutOverrides="GridBox" FontSize="20" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" TextTrimming="WordEllipsis"/>
22: </StackPanel>
23: </Grid>
24: </Grid>
25: </Viewbox>
26:
27: </DataTemplate>
даже в такой!:
И это все просто декларативно, без изменения любой логики ассоциированный с ListBox.
Демонстрация этого примера вживую доступна в моем докладе на TechDays.ru.
Однако, уже несколько раз те, кто применяет DataTemplates, задавали мне вопрос: как избавится от стандартного системного маркера выделения?
В частности мне прислали подобный пример:
Кто-то мне рассказывал, что ради этого они сильно помучились и изменяли структуру визуализации ListBox через переопределение Control Template.
На самом деле есть очень простой способ:
На уровне ресурсов конкретного ListBox, или в вышележащих ресурсах, или в ресурсном файле просто делаем цвет выделения прозрачным (Transparent):
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
И все:
Наиболее правильно это можно сделать в стиле:
1: <Style x:Key="listBoxStyle1" TargetType="{x:Type ListBox}">
2: <Style.Resources>
3: <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
4: </Style.Resources>
5: ...
Таким образом, данное переопределение будет применяться только к ListBox, ассоциированным с данным стилем, а все остальные элементы будут отрабатывать по умолчанию - архив с данным примером прикреплен к посту.
Comments
Anonymous
April 03, 2009
Спасибо автору за полезную информацию ;)Anonymous
April 07, 2009
Интересно стало, а есть кто-то, кто не согласен с автором ? :)Anonymous
June 12, 2009
PingBack from http://greenteafatburner.info/story.php?id=3760Anonymous
June 07, 2010
Спасибо! Ответили на многие вопросы!:)