Silverlight List Item Style

How would one create a list style so that the selection has a different text color than the default view? I've looked at this in several ways and because the ContentPresenter doesn't have a Foreground property.

The default control template in the list contains several rectangles that you can use to customize the highlight color. For example, with the default style, the BGColor3 rectangle has its own opacity adjusted for a selection effect.

Here's the bulk of my control pattern:

<Grid>
    <Rectangle x:Name="BGColor2" Fill="{StaticResource HoverBrush}" Stroke="Black" StrokeThickness="1" Opacity="0"/>
    <Rectangle x:Name="BGColor3" Fill="{StaticResource ListboxHighlightBrush}" StrokeThickness="0" Opacity="0"/>
    <Rectangle x:Name="BGColor" Stroke="Black" StrokeThickness="0" Opacity="0.2" Fill="{TemplateBinding Background}"/>
    <Border Height="20">
        <ContentPresenter HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
    </Border>
    <Rectangle Fill="Blue" Opacity="0.4" x:Name="FocusVisual" Stroke="#BF313131" Margin="1" StrokeThickness="1" StrokeDashArray="1 2" StrokeDashCap="Square" Visibility="Collapsed" />
    <Rectangle x:Name="BorderRect" Stroke="Black" StrokeThickness="1" Opacity="0.3" />
</Grid>

      

In the Visual State selection area, here's the gist:

<VisualStateGroup x:Name="SelectionStates">
    <VisualState x:Name="Unselected"/>
    <VisualState x:Name="Selected">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="BGColor2" Storyboard.TargetProperty="(UIElement.Opacity)">
                <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.8"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

      

Obviously the BGColor2 rectangle changes (opacity) so that the selected item has a background. Fair enough. Within this part of the storyboard, is there anyway to access the ContentPresenter or something like that and toggle the foreground text color?

Footnote: Wouldn't it be much cleaner to just have different templates versus visual state transitions?

---- added after the first answer ----

Using a TextBlock almost does the trick, but what is interesting is that the transition for SelectedUnfocused does not seem coercive, which means that the implementation of your solution works fine until the person navigates to the previously selected element, then the text goes to black again.

Here's my template:

<!-- ItemStyle brushes -->
<SolidColorBrush x:Key="BaseColorBrush" Color="White"/>
<SolidColorBrush x:Key="BaseColorBrushFaint" Color="#265B0000"/>
<SolidColorBrush x:Key="ForegroundColorBrush" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="HoverBrush2" Color="#FF808000"/>
<LinearGradientBrush x:Key="HoverBrush"  EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FF406DC7" Offset="1"/>
    <GradientStop Color="#FF002C83"/>
</LinearGradientBrush>

<LinearGradientBrush x:Key="ListboxHighlightBrush" EndPoint="0.5,1" StartPoint="0.5,0">
    <GradientStop Color="#FF7CA8FF" Offset="1"/>
    <GradientStop Color="#FF376FDC"/>
</LinearGradientBrush>

<SolidColorBrush x:Key="HyperlinkBrush" Color="#FFC8A1A1"/>

<!-- Search Listbox ItemStyle -->
<Style x:Key="ItemStyle" TargetType="ListBoxItem">
    <Setter Property="Padding" Value="4"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Top"/>
    <Setter Property="Background" Value="{StaticResource BaseColorBrush}"/>
    <Setter Property="BorderBrush" Value="{StaticResource HoverBrush}"/>
    <Setter Property="Foreground" Value="#FF333333"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="TabNavigation" Value="Local"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBoxItem">
                <Grid>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver">
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="BGColor3" Storyboard.TargetProperty="Opacity" Duration="0" To="1"/>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="BGColor" Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.3"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
                                        <EasingColorKeyFrame KeyTime="00:00:00" Value="White"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.55"/>
                                    </DoubleAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="SelectionStates">
                            <VisualState x:Name="Unselected"/>
                            <VisualState x:Name="Selected">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="BGColor2" Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.9"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
                                        <EasingColorKeyFrame KeyTime="00:00:00" Value="White"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="SelectedUnfocused">
                                <Storyboard>
                                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="BGColor2" Storyboard.TargetProperty="(UIElement.Opacity)">
                                        <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.9"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
                                        <EasingColorKeyFrame KeyTime="00:00:00" Value="#FFFFFFFF"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="FocusStates">
                            <VisualState x:Name="Focused">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusVisual" Storyboard.TargetProperty="Visibility" Duration="0">
                                        <DiscreteObjectKeyFrame KeyTime="0">
                                            <DiscreteObjectKeyFrame.Value>
                                                <Visibility>Visible</Visibility>
                                            </DiscreteObjectKeyFrame.Value>
                                        </DiscreteObjectKeyFrame>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="contentPresenter" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)">
                                        <EasingColorKeyFrame KeyTime="00:00:00" Value="White"/>
                                    </ColorAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Unfocused">
                                <Storyboard/>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Rectangle x:Name="BGColor2" Fill="{StaticResource HoverBrush}" Stroke="Black" StrokeThickness="0" Opacity="0"/>
                    <Rectangle x:Name="BGColor3" Fill="{StaticResource ListboxHighlightBrush}" StrokeThickness="0" Opacity="0"/>
                    <Rectangle x:Name="BGColor" Stroke="Black" StrokeThickness="0" Opacity="0.3" Fill="{TemplateBinding Background}"/>
                    <Border Height="20">
                        <TextBlock Canvas.ZIndex="22" x:Name="contentPresenter" Foreground="{TemplateBinding Foreground}"
                            Text="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding 
                            HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" />
                    </Border>
                    <Rectangle  Opacity="0.4" x:Name="FocusVisual" Stroke="#BF313131" Margin="1" StrokeThickness="1" StrokeDashArray="1 2" StrokeDashCap="Square" Visibility="Collapsed" />
                    <Rectangle x:Name="BorderRect" Stroke="Black" StrokeThickness="0" Opacity="0.3" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

      

And my consumption of the template:

    <ListBox ItemContainerStyle="{StaticResource ItemStyle}" x:Name="testListBox" />

      

And finally, some code to populate the list:

            List<string> data = new List<string>();
            for (int i = 0; i < 30; i++) { 
                data.Add(DateTime.Now.AddDays(i).ToString("MMMM dd yyyy"));
            }           
            testListBox.ItemsSource = data;         

      

+2


source to share


2 answers


Change the ContentPresenter in your template to ContentControl, which has a Foreground property that you can use for TemplateBind.



+6


source


I tried your scenario. By default, the content of the default list is a string that is black. The listbox element has a foreground property that you can set, but I'm not sure where it is in the template. They did something special for the strings to use the foreground, but didn't reveal it in the template. You can try a hack if you know you will always have text content to replace the contentpresenter of the controltemplate with a text block that has a forground. (To edit the ListItem template, right click it in Blend3 and go to Edit Template, Edit Copy and change the new style

<ContentPresenter x:Name="contentPresenter" 
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" />

      

to



<TextBlock x:Name="contentPresenter" Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding 
HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" />

      

I added TemplateBinding for text and foreground. You should be able to manipulate the foreground in visual states to make the correct states look disabled, selected, etc. I hope this helps.

+2


source







All Articles