I need to create a list type control that meets the following requirements:
- Show an icon delete right next to the text of each item.
- Must show the added elements horizontally.
- When clicking on the delete icon, the control must be able to remove it from the ItemsSource, and these changes must also be reflected to the property to which the ItemsSource is linked.
- Must always work, regardless of the type linked to the ItemsSource property of the control.
For this I have made a custom control that inherits from listview:
Imports System.Windows.Controls.Primitives
Imports System.Reflection
Public Class ListCustomControl
Inherits System.Windows.Controls.ListView
Shared Sub New()
'Esta llamada a OverrideMetadata indica al sistema que este elemento desea proporcionar un estilo diferente al de su clase base.
'Este estilo se define en themes\generic.xaml
DefaultStyleKeyProperty.OverrideMetadata(GetType(ListCustomControl), New FrameworkPropertyMetadata(GetType(ListCustomControl)))
End Sub
Public Overrides Sub OnApplyTemplate()
MyBase.OnApplyTemplate()
End Sub
Private Sub ListCustomControl_Loaded(sender As Object, e As System.Windows.RoutedEventArgs) Handles Me.Loaded
AddHandler MyBase.PreviewMouseLeftButtonDown, AddressOf OnPreviewMouseLeftButtonDown
End Sub
Private Overloads Sub OnPreviewMouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
If e.OriginalSource.GetType Is GetType(Controls.Image) Then
CType(Me.ItemsSource, IList).Remove(CType(e.OriginalSource, Image).DataContext)
End If
End Sub
End Class
Here's the generic.xaml associated with ListCustomControl:
<Style TargetType="{x:Type local:ListCustomControl}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ListCustomControl}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="1" SnapsToDevicePixels="true">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate" >
<Setter.Value>
<DataTemplate x:Name="ItemTemplate">
<Border x:Name="Border"
Padding="2"
CornerRadius="5"
HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid x:Name="LayoutGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label x:Name="LabelText"
Grid.Column="0"
Foreground="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=LabelTextColor}"
Content="{Binding Name}"
Padding="2,0,2,0"
FontStyle="Italic" />
<Border x:Name="PART_IconBorder"
Grid.Column="1"
BorderThickness="1"
Background="White"
VerticalAlignment="Top"
HorizontalAlignment="Left"
BorderBrush="White">
<Image x:Name="Icon"
Stretch="None"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Source="/ListCustomControl;component/Resources/Images/delete.gif" />
</Border>
</Grid>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Everything works fulfilling the requested requirements, but I have one doubt:
How could I make the content of the labeltext work against the DisplayMemberPath property of ListCustomControl instead of being forced to bind it to the name property as it is now?