I'm trying to give a style to items in a ListBox
, I made this style previously for ListViewItem which about TextBlock, Image and a Border which changes its color when an item event raised (IsSelected, IsMouseOver, IsSelectionActive), Now I want to keep this style and apply it to any item added to a ListBox
<Style x:Key="ListBoxPCInfoStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68">
<Image x:Name="Img" Width="56" Height="56" Margin="6,0,6,18" Source="{Binding RelativeSource={RelativeSource TemplatedParent}, Path= ActualHeight}"/>
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="74" VerticalAlignment="Top" Width="68" CornerRadius="2.5"/>
<TextBlock HorizontalAlignment="Stretch" TextWrapping="Wrap" Text="{TemplateBinding Name}" VerticalAlignment="Bottom" Width="Auto" Height="17" TextAlignment="Center" Margin="4,0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#33C1DEFF" Offset="0"/>
<GradientStop Color="#41A5CDFF" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="BorderBrush" TargetName="border" Value="#FF7DA2CE"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7DA2CE"/>
<Setter Property="Background" TargetName="border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#97C1DEFF" Offset="0"/>
<GradientStop Color="#A7A5CDFF" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="Selector.IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="border" Value="#FFB4B4B4"/>
<Setter Property="Background" TargetName="border">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#7FE5E5E5" Offset="0"/>
<GradientStop Color="#B2CCCCCC" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I have this ListBox
<ListBox x:Name="ListHosts" Background="{x:Null}" BorderBrush="{x:Null}">
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Left" Height="20" VerticalAlignment="Top" Width="50" CornerRadius="2.5"/>
<Image x:Name="Img" Source="BtnImg/Computer.png" Stretch="None" Margin="3,0,10,0"/>
<TextBlock x:Name="PCName" Margin="0,7" TextWrapping="Wrap" Height="16" HorizontalAlignment="Left"><Run Text="{Binding Name}"/></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox>
I feel like I'm missing something simple here... can someone help me spot it?
2 Options:
Either remove the
x:Key
from the style:this will make the style apply to all
ListBoxItem
s in the resource scope.or
Explicitly reference the style in your
ListBox
:-------------------------------------------------------------------------------------------
Anyways, all your XAML is wrong. You're defining the
ListBoxItem.Template
like this:Which leaves no chance for custom
DataTemplates
to be introduced anywhere. You need to leave aContentPresenter
somewhere, so that WPF has a chance to put DataTemplated content inside that.And the
TextBlock
makes no sense. You're binding against theListBoxItem.Name
property, which is completely irrelevant and makes no sense to be shown in the UI, and which you have no control over, anyways.Data does not belong into
ControlTemplate
s, onlyDataTemplate
s.Change your template like so:
And the
ListBox
XAML is also wrong:By doing this:
You're putting the
DataTemplate
as an item inside the ListBox, which is not what you want. You need to specifically assign theDataTemplate
as theItemTemplate
for theListBox
:And why is the
Image.Source
bound to a property of typedouble
? That makes no sense. Either put a specific resource there:or
if you want to dynamically change the image dependending on certain data, then that belongs into the
DataTemplate
, not theControlTemplate
.-------------------------------------------------------------------------------------------
I suggest you read up the following material: