Change expander arrow - wpf

So playing around with the expander control and I came across this code to set the expander colour while closed. But I noticed that the arrow part of the expander remained white. Is there a way to either remove the Arrow or colour that region?
Screen Shot:
Bare in mind I have no experience with this at all, and I dont know how to edit templates etc
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" OpacityMask="#91000000">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Border" x:Key="RacePitBorderStyle" >
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BackBrush}"/>
</Style>
<DataTemplate x:Key="titleText">
<Border Style="{StaticResource RacePitBorderStyle}" Height="24">
<TextBlock Text="{Binding}"
Margin="4 0"
VerticalAlignment="Center"
Foreground="White"
FontSize="11"
FontWeight="Normal"
Width="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type Expander}},
Path=ActualWidth}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
<Style TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate" Value="{StaticResource titleText}"/>
</Style>
</StackPanel.Resources>
<Expander Name="hcontCtrl" Header="This is the header.">
<StackPanel>
<TextBox>This is a textbox</TextBox>
<Button>A button</Button>
</StackPanel>
</Expander>
</StackPanel>
</Page>

The arrow is part of the default control template, you could either copy that and modify it or create your own from scratch.

Related

How to draw expander (slider) in wpf

I have a requirement where I need a button which will let the user tap and swipe down/up in order to expand/collapse the control above the button. Something like in this image:
How can I achieve it in xaml?
You can create Template for Header and put an image from your question into HeaderTemplate. Let me show an example:
<Grid>
<Grid.Resources>
<Style TargetType="Border" x:Key="FooBorderStyle" >
<Style.Resources>
<LinearGradientBrush x:Key="ABackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource ABackBrush}"/>
</Style>
<DataTemplate x:Key="titleTemplate">
<Border Style="{StaticResource FooBorderStyle}" Height="24">
<Image Source="../Images/yourImage.png"
Margin="4 0"
VerticalAlignment="Center"/>
</Border>
</DataTemplate>
<Style TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate" Value="{StaticResource titleTemplate}"/>
</Style>
</Grid.Resources>
<Expander Name="hcontCtrl" Header="This is the header.">
<StackPanel>
<TextBox>This is a textbox</TextBox>
<Button>A button</Button>
</StackPanel>
</Expander>
</Grid>

apply an existed style for ListBoxItem template

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:
<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:
MSDN: WPF Content Model
MSDN: WPF Controls Content Model
Dr. WPF: ItemsControls A to Z

listbox design issue

i am trying to design some nice listbox, but every time i click on the item in the listbox
a selection background is ruined everything...
how can i make it irrelevant ?
this is the XAML:
<!-- Site List View -->
<ListBox Grid.Row="1" Name="SiteListBox" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch">
<ListBox.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="Gainsboro" Offset="0.805" />
</LinearGradientBrush>
</ListBox.Background>
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="Control.Padding" Value="0"></Setter>
<Style.Triggers>
<Trigger Property="ListBoxItem.IsSelected" Value="True">
<Setter Property="ListBoxItem.Background" Value="DarkRed" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" CornerRadius="4"
Background="{Binding Path=Background, RelativeSource={
RelativeSource
Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}
}}">
<TextBlock Margin="5" Text="{Binding Path=Name}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
a also attached a print screen.
You can change the default colors for when a ListBoxItem container IsSelected. Set them to Transparent to get the effect that you're after
<ListBox ...>
<ListBox.Resources>
<!-- Brush for selected item that doesn't have focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
<!-- Brush for selected item that has focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
</ListBox.Resources>
<!-- ... -->
</ListBox>

WindowsFormsHost not showing when Wpf Window style is set

I have a WPF Window that has a WinForms Button inside. When I set the Style of the Window the button isn't rendered, but when the Window Style is not set the Button appears as it should be.
Window Xaml:
<Window x:Class="Telbit.TeStudio.View.Forms.FloatingTestComponentsBrowser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
Title="Test Components Browser" Style="{DynamicResource TSHUD}"
SizeToContent="WidthAndHeight" Closing="Window_Closing" >
<Grid Name="windowContent" Height="300" Width="300">
<WindowsFormsHost HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<wf:Button Text="Try" Name="btnTry" MaximumSize="100,25" BackColor="LightGray"/>
</WindowsFormsHost>
</Grid>
</Window>
Here is the Style for the window:
<Style x:Key="TSHUD" TargetType="{x:Type Window}">
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="BorderThickness" Value="0px"/>
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Grid x:Name="LayoutRoot">
<Rectangle Fill="#ED111F29" Stroke="Black" Margin="29,29,29,29" RadiusX="3" RadiusY="3" Effect="{DynamicResource TSWindowShadow}"/>
<Rectangle Name="TSHUDHeader" Stroke="Black" Margin="29,29,29,29" VerticalAlignment="Top" Height="25" RadiusX="3" RadiusY="3">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#ED1F3A45"/>
<GradientStop Color="#EC111F29" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Name="TSHUDHeaderSplitter" Fill="#ED374551" Margin="30,54,30,29" VerticalAlignment="Top" Height="1"/>
<Label Name="TSHudTitle" Background="Transparent"
Margin="41,34,41,29" Padding="0"
HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="20" >
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}, AncestorLevel=1}, Path=Title}"
TextWrapping="Wrap" Foreground="#FF8395B1" FontWeight="Bold"/>
</Label>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have other windows with the same style but only with WPF controls (some with default style and some with custom style) and there is no problem.
I've tried to Enable Visual Styles with no luck..
Thanks in advance for any help...

WPF - Only want one expander open at a time in grouped Listbox

I have a UserControl with a templated grouped listbox with expanders and only want one expander open at any time. I have browsed through the site but haven't found anything except binding the IsExpanded to IsSelected which isn't quite what I want.
I am trying to put some code in the Expanded event that would loop through Expanders and close all the ones that aren't the expander passed in the Expanded event. I can't seem to figure out how to get at them. I've tried ListBox.Items.Groups but didn't see how to get at them and tried ListBox.ItemContainerGenerator.ContainerFromItem (or Index) but nothing came back.
Thanks
Here is the current markup:
<ListBox Name="ListBox">
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Border BorderBrush="CadetBlue" BorderThickness="1">
<Expander BorderThickness="0,0,0,1" Expanded="Expander_Expanded"
Focusable="False"
IsExpanded="{Binding IsSelected,
RelativeSource={RelativeSource FindAncestor, AncestorType=
{x:Type ListBoxItem}}}" >
<Expander.Header>
<Grid>
<StackPanel Height="30" Orientation="Horizontal">
<TextBlock Foreground="Navy" FontWeight="Bold"
Text="{Binding Path=Name}" Margin="5,0,0,0"
MinWidth="200" Padding="3"
VerticalAlignment="Center" />
<TextBlock Foreground="Navy" FontWeight="Bold"
Text=" Setups: " VerticalAlignment="Center"
HorizontalAlignment="Right"/>
<TextBlock Foreground="Navy" FontWeight="Bold"
Text="{Binding Path=ItemCount}"
VerticalAlignment="Center"
HorizontalAlignment="Right" />
</StackPanel>
</Grid>
</Expander.Header>
<Expander.Content>
<Grid Background="white" >
<ItemsPresenter />
</Grid>
</Expander.Content>
<Expander.Style >
<Style TargetType="{x:Type Expander}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientStop Color="WhiteSmoke"
Offset="0.0" />
<GradientStop Color="Orange" Offset="1.0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="false"
<Setter Property="Background">
<Setter.Value>
...
In the ListBoxItem's template you can use RadioButtons that share the same group, bind their IsChecked to IsSelected of the ListBoxItem and retemplate it as Expander, so you can bind the IsExpanded to IsChecked on the TemplatedParent.

Resources