WPF ListBox и DataTemplates – В чем их сила и как избавиться от стандартного синего маркера выделения?


В очередной раз получил данный вопрос и решил поделиться ответом со всеми.


Как я думаю, многие знают, DataTemplates являются мощнейшим механизмом, позволяющим переопределять визуализацию элементов управления, выводящих множество элементов данных (ListBox, ListView, TreeView...).


С помощью них вы можете выводить в рамках одного визуального шаблона сразу множество аттибутов элемента данных.


Например, имея данный ListBox:


image


Я могу применив данный 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>

превратить его в


image


или применив данный 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>

даже в такой!:


image


И это все просто декларативно, без изменения любой логики ассоциированный с ListBox.


Демонстрация этого примера вживую доступна в моем докладе на TechDays.ru.


Однако, уже несколько раз те, кто применяет DataTemplates, задавали мне вопрос: как избавится от стандартного системного маркера выделения?


В частности мне прислали подобный пример:


image


Кто-то мне рассказывал, что ради этого они сильно помучились и изменяли структуру визуализации ListBox через переопределение Control Template.


На самом деле есть очень простой способ:


На уровне ресурсов конкретного ListBox, или в вышележащих ресурсах, или в ресурсном файле просто делаем цвет выделения прозрачным (Transparent):


<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />

И все:


image


Наиболее правильно это можно сделать в стиле:



   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, ассоциированным с данным стилем, а все остальные элементы будут отрабатывать по умолчанию - архив с данным примером прикреплен к посту.


Источник 1, Источник 2

WpfApplication3.zip

Comments (4)
  1. Спасибо автору за полезную информацию 😉

  2. Андрей says:

    Интересно стало, а есть кто-то, кто не согласен с автором ? 🙂

  3. konrin says:

    Спасибо! Ответили на многие вопросы!:)

Comments are closed.

Skip to main content