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>
Related
I tried to set up a custom styled treeview that does "just in time" loading by two-way binding the expanded property to a similar property in the view-model. The style and functionality aspects work fine on their own, but not when put together.
When I do it like this the functionality is there:
<TreeView Name="treeView" ItemsSource="{Binding}" Grid.Column="0">
<TreeView.Resources>
<ResourceDictionary Source="GroupedTreeViewItemStyle.xaml"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding Expanded, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
But when I add the BasedOn to use my custom style it does no longer load any nodes.
I use my style by replacing the above style definition with the following:
<Style TargetType="TreeViewItem" BasedOn="{StaticResource GroupedTreeViewItemStyle}">
And here is my custom style based on this tutorial:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:this="*******namespace omitted*******">
<!-- This Style redefines the ControlTemplate used by TreeViewItems and
also provides a different itemspanel for their child items. -->
<Style TargetType="TreeViewItem" x:Key="GroupedTreeViewItemStyle">
<Style.Resources>
<LinearGradientBrush x:Key="ItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemAreaBrush" StartPoint="0.5, 0" EndPoint="0.5, 1" Opacity="1">
<GradientStop Color="#fff" Offset="0" />
<GradientStop Color="#f2fcfe" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="ItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="SelectedItemBorderBrush" StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="#243B55" Offset="0" />
<GradientStop Color="#141E30" Offset="1" />
</LinearGradientBrush>
<DropShadowBitmapEffect x:Key="DropShadowEffect" />
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid Margin="8,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- This Border contains elements which display
the content and child items of the TreeViewItem. -->
<Border Name="Bd"
Background="{StaticResource ItemAreaBrush}"
BorderBrush="{StaticResource ItemBorderBrush}"
BorderThickness="0.6"
CornerRadius="8"
Padding="6"
SnapsToDevicePixels="True"
>
<Grid>
<!-- Items with children are
shown in an Expander. -->
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
<Expander.Header>
<!-- Displays the item's header in the Expander. -->
<ContentPresenter ContentSource="Header" />
</Expander.Header>
<!-- Displays the item's children. -->
<ItemsPresenter />
</Expander>
<!-- Items without children are
shown in a ContentPresenter. -->
<ContentPresenter Name="CntPres"
ContentSource="Header"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Visibility="Collapsed"
/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<!-- If the TreeViewItem has child items,
show it in an Expander. Otherwise
hide the Expander and show the hidden
ContentPresenter. -->
<Trigger Property="TreeViewItem.HasItems" Value="false">
<Setter
TargetName="Exp"
Property="Visibility"
Value="Collapsed" />
<Setter
TargetName="CntPres"
Property="Visibility"
Value="Visible" />
</Trigger>
<!--When the item is selected in the TreeView, use the
"selected" colors and give it a drop shadow. -->
<Trigger Property="IsSelected" Value="true">
<Setter
TargetName="Bd"
Property="Panel.Background"
Value="{StaticResource SelectedItemAreaBrush}" />
<Setter
TargetName="Bd"
Property="Border.BorderBrush"
Value="{StaticResource SelectedItemBorderBrush}" />
<!--<Setter
TargetName="Bd"
Property="TextElement.Foreground"
Value="{DynamicResource
{x:Static SystemColors.HighlightTextBrushKey}}" />-->
<Setter
TargetName="Bd"
Property="Border.BitmapEffect"
Value="{StaticResource DropShadowEffect}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Make each TreeViewItem show it's children
in a StackPanel. If it is a root item then
the Orientation will be 'Horizontal', else
'Vertical'. -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<ItemsPanelTemplate.Resources>
<this:ItemsPanelOrientationConverter x:Key="conv" />
</ItemsPanelTemplate.Resources>
<StackPanel
IsItemsHost="True"
Orientation="{Binding
RelativeSource={x:Static RelativeSource.TemplatedParent},
Converter={StaticResource conv}}"
/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Does anybody know, what I am doing wrong in combining the style and functionality of my tree?
Is the problem that the style already defines something according to the isExpanded property? Or is there something missing, something along the lines of super(isExpanded)?
Thanks for your help!
Expander binding is probably the cause of the issue:
<Expander Name="Exp" IsExpanded="{TemplateBinding TreeViewItem.IsExpanded}">
according to documentation,
A TemplateBinding is always a one-way binding, even if properties involved default to two-way binding.
(see also TemplateBinding limitations)
try re-write binding as:
<Expander Name="Exp"
IsExpanded="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}">
I am using custom ComboBox with style, I want to set width of a Popup dynamically via coading so that to auto adjust the width of popup
so I wanted to change Popup like second image dynamically(whatever may be thesize of ComboBox)
I am using style as follows
<Style x:Key="ComboBoxStyle" TargetType="{x:Type ComboBox}">
<Setter Property="Foreground" Value="#666666"/>
<Setter Property="FontFamily" Value="Arial"/>
<Setter Property="FontSize" Value="13"/>
<Setter Property="Height" Value="28"/>
<Setter Property="BorderThickness" Value="1.5"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Popup Margin="1" x:Name="PART_Popup" AllowsTransparency="true" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Placement="Bottom" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Grid.ColumnSpan="2" Width="{Binding ActualWidth,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}">
<Border Name="DropDownBorder" Width="Auto" Height="Auto" BorderThickness="1,0,1,1" CornerRadius="0,0,4,4" BorderBrush="#FFbbbbbb">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFE9E9E9" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<ScrollViewer CanContentScroll="true">
<ItemsPresenter />
</ScrollViewer>
</Border>
</Popup>
<ToggleButton Style="{StaticResource cmbToggle}" Grid.ColumnSpan="2" IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"/>
<ContentPresenter HorizontalAlignment="Left" Margin="5,0,0,0" VerticalAlignment="Center" IsHitTestVisible="false" Content="{TemplateBinding SelectionBoxItem}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="cmbToggle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Name="cmbBorder" CornerRadius="3" BorderBrush="#FFaaaaaa" BorderThickness="1.5">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0" />
<GradientStop Color="#FFE9E9E9" Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Border BorderBrush="#FFaaaaaa" BorderThickness="1,0,0,0" Width="20" HorizontalAlignment="Right">
<Polygon Name="pol" Fill="#FF787878" Points="4,9 8,14 12,9" Stroke="#FF787878" StrokeThickness="0" Margin="1 1 0 0">
</Polygon>
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="CornerRadius" TargetName="cmbBorder" Value="4,4,0,0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So My idea is to change width of Popup dynamically(Combobox width - togglebutton width = popup width).I have written style in App.xaml
How to do this, Please help me. Thanks in advance.
Ok so in your ToggleButton Style we can see the Border holding Polygon arrow is 20 in Width. That's the Width to be removed from the Popup
Thus we can do something like:
Firstly add 2 Column's to the Grid in ComboBox ControlTemplate
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<!-- New Bit -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<!-- End of New Bit -->
<Popup x:Name="PART_Popup"
Grid.ColumnSpan="2"
...
and then update the Width of Popup to
<Popup x:Name="PART_Popup"
Grid.ColumnSpan="2"
Width="{Binding Path=ColumnDefinitions[0].ActualWidth,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType=Grid}}"
...
Your Style already has ColumnSpan mentioned on appropriate controls, so nothing else is needed. This should give you the output your looking for.
you can directly use
<ComboBox.Resources>
<Style TargetType="{x:Type Popup}">
<Setter Property="Width" Value="110"/>
</Style>
</ComboBox.Resources>
Using Dhaval Patel's solution bound to a view model property did the trick.
I calculate the max width using FormattedText when the collection changes and it bind it below.
<ComboBox.Resources>
<Style TargetType="{x:Type Popup}">
<Setter Property="Width" Value="{Binding MaxWidthOfMyCollection"/>
</Style>
</ComboBox.Resources>
I want to create a custom WPF dropdown menu, so I created a User control which contains a ToggleButton and a Popup control. The popup appears when I click on the button.
Now I want to add a mouse hover effect on the menu items in the popup: but the LinearGradientBrush is not working with alpha channels:
<UserControl.Resources>
...
<Style x:Key="SubMenuItemStyle" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="MenuItem">
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" ClipToBounds="True">
<Rectangle x:Name="rectangle" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"
Fill="{TemplateBinding Background}" />
<StackPanel>
<TextBlock x:Name="text" Text="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" />
</StackPanel>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="rectangle" Value="#30000000"/>
<Setter Property="Fill" TargetName="rectangle">
<Setter.Value>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="#10000000" Offset="0"/>
<GradientStop Color="#10FFFFFF" Offset="1"/>
<!-- Not works... -->
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" TargetName="text" Value="#FF9A9A9A"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Controls:ToggleImageButton Style="{DynamicResource ArrowMenuStyle}" x:Name="imageButton" Height="21" />
<Popup x:Name="popup" PlacementTarget="{Binding ElementName=imageButton}" Placement="Bottom" StaysOpen="False" IsOpen="{Binding ElementName=imageButton, Path=IsChecked}">
<ItemsControl ItemsSource="{Binding MenuCommands}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Name}" Command="{Binding Command}" Background="{Binding ElementName=popupMenuControl, Path=MenuBackground}" Foreground="{Binding ElementName=popupMenuControl, Path=MenuForeground}" Click="MenuItem_Click" Style="{StaticResource SubMenuItemStyle}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Popup>
</Grid>
When I set the GradientBrush to this, everything works fine:
<LinearGradientBrush EndPoint="0,0" StartPoint="1,1">
<GradientStop Color="Green" Offset="0"/>
<GradientStop Color="Yellow" Offset="1"/>
</LinearGradientBrush>
But it seems the Alpha channel breaks the whole thing, and what I see is a black rectangle.
...Any idea?
If I put the MenuItems inside a Menu container, the Menu overrides my styles...
Thanks in advance!
have you set AllowsTransparency to true?
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.
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>