Question

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?

Was it helpful?

Solution

2 Options:

Either remove the x:Key from the style:

 <Style TargetType="{x:Type ListBoxItem}">
    <!-- ... -->

this will make the style apply to all ListBoxItems in the resource scope.

or

Explicitly reference the style in your ListBox:

<ListBox ItemContainerStyle="{StaticResource ListBoxPCInfoStyle}">
    <!-- ... -->

-------------------------------------------------------------------------------------------

Anyways, all your XAML is wrong. You're defining the ListBoxItem.Template like this:

                <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>

Which leaves no chance for custom DataTemplates to be introduced anywhere. You need to leave a ContentPresenter somewhere, so that WPF has a chance to put DataTemplated content inside that.

And the TextBlock makes no sense. You're binding against the ListBoxItem.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 ControlTemplates, only DataTemplates.

Change your template like so:

                <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"/>
                    <ContentPresenter ContentSource="Content"/> 
                </Grid>

And the ListBox XAML is also wrong:

By doing this:

<ListBox ...>
  <DataTemplate>
      <!-- ... -->
  </DataTemplate>
</ListBox>

You're putting the DataTemplate as an item inside the ListBox, which is not what you want. You need to specifically assign the DataTemplate as the ItemTemplate for the ListBox:

<ListBox ...>
   <ListBox.ItemTemplate>
      <DataTemplate>
          <!-- ... -->
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

And why is the Image.Source bound to a property of type double? That makes no sense. Either put a specific resource there:

<Image Source="/resources/somepic.png"/>

or

if you want to dynamically change the image dependending on certain data, then that belongs into the DataTemplate, not the ControlTemplate.

-------------------------------------------------------------------------------------------

I suggest you read up the following material:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top