Change Silverlight Chart Legend Item Layout - silverlight

I am working on customizing the layout of a Silverlight Toolkit Chart. I have two requirements:
1) Move the Legend area to the bottom of the chart (solved).
2) change the layout of elements within the legend to be displayed next to each other,
ie. {legend 1},{legend 2},{legend 3}, rather than the default column format.
1) was easy to solve with a ControlTemplate (see below).
2) How do I change the layout of legend items? Can it be done by further customizing the Chart's ControlTemplate, or does the Legend need its own ControlTemplate?
The Chart itself is defined as:
<chartingToolkit:Chart Name="chartCompareMain"
Template="{StaticResource ChartLayoutLegendBottom}">
<chartingToolkit:Chart.Axes>
<chartingToolkit:DateTimeAxis Orientation="X"
AxisLabelStyle="{StaticResource ChartDateFormat}">
</chartingToolkit:DateTimeAxis>
<chartingToolkit:LinearAxis Orientation="Y"/>
</chartingToolkit:Chart.Axes>
</chartingToolkit:Chart>
The ControlTemplate to move the legend items (based on the default template) is:
<ControlTemplate x:Key="ChartLayoutLegendBottom" TargetType="chartingToolkit:Chart">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<dataviz:Title Grid.Row="0" Content="{TemplateBinding Title}" Style="{TemplateBinding TitleStyle}" />
<Grid Grid.Row="1" Margin="0,15,0,15">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<chartingprimitives:EdgePanel x:Name="ChartArea" Style="{TemplateBinding ChartAreaStyle}" Grid.Column="0" >
<Grid Canvas.ZIndex="-1" Style="{TemplateBinding PlotAreaStyle}" />
<Border Canvas.ZIndex="10" BorderBrush="#FF919191" BorderThickness="1" />
</chartingprimitives:EdgePanel>
</Grid>
<dataviz:Legend x:Name="Legend" Header="{TemplateBinding LegendTitle}" Style="{TemplateBinding LegendStyle}" Grid.Row="2"/>
</Grid>
</Border>
</ControlTemplate>

For completeness sake, here is the LegendStyle="{StaticResource BottomLegendLayout} (very useful tool to figure out styles is the Silverlight Default Style Browser)
<Style x:Name="BottomLegendLayout" TargetType="dataviz:Legend">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="chartingToolkit:LegendItem" >
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="chartingToolkit:LegendItem">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="2,2,5,2">
<Rectangle Width="8" Height="8" Fill="{Binding Background}" Stroke="{Binding BorderBrush}" StrokeThickness="1" Margin="0,0,3,0" VerticalAlignment="Center" />
<dataviz:Title Content="{TemplateBinding Content}" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="TitleStyle">
<Setter.Value>
<Style TargetType="dataviz:Title">
<Setter Property="Margin" Value="0,5,0,10" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel"> <!-- change layout container for legend items to be horizonal -->
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dataviz:Legend">
<!-- This is the border around the legend area.
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="2">
-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<!-- Uncomment the next line to show a grid title. -->
<!--<dataviz:Title Grid.Row="0" x:Name="HeaderContent" Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}" Style="{TemplateBinding TitleStyle}"/>-->
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" BorderThickness="0" Padding="0" IsTabStop="False">
<ItemsPresenter x:Name="Items" />
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Adding the following to the chart will do the trick (from here):
<chartingToolkit:Chart.LegendStyle>
<Style TargetType="dataviz:Legend">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
</chartingToolkit:Chart.LegendStyle>

Related

How to draw a separator line below DataGrid headers in WPF

Is there a way to draw a separator line below the headers in a DataGrid? I have set GridLinesVisibility to None as I don't want any gridlines except the one below the headers. I'm struggling to find a way to do this and any help would be greatly appreciated.
This is what I want to achieve.
You can modify the DataGridColumnHeader's ControlTemplate.
I used the original DataGrid's template and replaced the default border and fill with a Rectangle with a height of 1.
<DataGrid>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Style.Resources>
<!-- This style is required for the column resize thumbs -->
<Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Cursor" Value="SizeWE" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid Background="White">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="1"/>
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
<Thumb Grid.Row="0" x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb Grid.Row="0" x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}" />
<Rectangle Grid.Row="1" Height="1" HorizontalAlignment="Stretch" Stroke="Black"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>

How can modify the wpf Expander so that the expander button is next to header text and center aligned and gets expanded down

I want to customize my expander
I have a grid and one of the column is expander with header text before the expander button. And the expander should expand and fill the complete row as shown in the picture.
I couldn't post images so the link is below.
http://i.stack.imgur.com/zVkpR.png
Can please somebody give me some thoughts how can I achieve this.
Update:
I have used the control template and was able to modify as needed but struck with one thing how to make the expanded portion fill the entire row of the containing grid.
Here is the sample code:
<Window x:Class="ExpanderStyles.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style x:Key="ExpanderHeaderStyle"
TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Padding="{TemplateBinding Padding}">
<Grid Background="Transparent"
SnapsToDevicePixels="False">
<Grid.RowDefinitions>
<RowDefinition Height="19"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="19"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Path x:Name="arrow" Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stroke="{TemplateBinding Foreground}"
StrokeThickness="1.5"
SnapsToDevicePixels="false"
Data="M 2,8 L 5.5,4.5 L 2,1">
<Path.LayoutTransform>
<RotateTransform Angle="0"/>
</Path.LayoutTransform>
</Path>
<ContentPresenter Grid.Column="0"
Margin="0,4,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
SnapsToDevicePixels="True"
RecognizesAccessKey="True"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="true">
<Setter Property="Data"
Value="M 1,4.5 L 4.5,1 L 8,4.5"
TargetName="arrow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="{x:Type Expander}"
TargetType="{x:Type Expander}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background"
Value="Transparent"/>
<Setter Property="HorizontalContentAlignment"
Value="Center"/>
<Setter Property="VerticalContentAlignment"
Value="Stretch"/>
<Setter Property="BorderBrush"
Value="Transparent"/>
<Setter Property="BorderThickness"
Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
CornerRadius="3"
SnapsToDevicePixels="true">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="19"/>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Canvas HorizontalAlignment="Center">
<ToggleButton x:Name="HeaderSite"
Margin="1"
MinWidth="0"
MinHeight="0"
Style="{StaticResource ExpanderHeaderStyle}"
IsChecked="{Binding Path=IsExpanded,Mode=TwoWay,RelativeSource={RelativeSource TemplatedParent}}"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
ContentTemplateSelector="{TemplateBinding HeaderTemplateSelector}"
Foreground="{TemplateBinding Foreground}"
Padding="{TemplateBinding Padding}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontStyle="{TemplateBinding FontStyle}"
FontStretch="{TemplateBinding FontStretch}"
FontWeight="{TemplateBinding FontWeight}"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"/>
</Canvas>
<ContentPresenter Grid.Row="1" x:Name="ExpandSite"
DockPanel.Dock="Bottom"
Visibility="Collapsed"
Focusable="false"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="{TemplateBinding Padding}">
</ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded"
Value="true">
<Setter Property="Visibility"
Value="Visible"
TargetName="ExpandSite"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0">Column 1</TextBlock>
<Expander Grid.Row="0" Grid.Column="1" Header="Details" ExpandDirection="Left">
<Grid Background="Blue">
<TextBlock Text="Details content" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="5" Foreground="White"></TextBlock>
</Grid>
</Expander>
<TextBlock Grid.Column="2" Grid.Row="0">Column 3</TextBlock>
</Grid>
</Window>
Any body has idea how to fill the parent grid row from control template?

WPF drag and drop only working when dropping on the items in the listview

So I have a listview in which I set up drag and drop, but for some reason it only lets me drop inside the actual items in the listview, rather than on any portion of the controltemplate that I overrode. How do I make it so that I can also do drag and drop over the textblock containing the title for the column?
<ListView
Margin="0,4,0,0"
Grid.Column="0"
x:Name="NameListView"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding Path = AddedItems}"
SelectionChanged="NameListView_SelectionChanged"
AllowDrop="True"
SelectionMode="Extended"
VirtualizingStackPanel.VirtualizationMode="Standard"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Border
Name="Border"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true"
Background="Transparent"
>
<ContentPresenter
Content="{TemplateBinding Content}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="true">
<Setter TargetName="Border"
Property="Background" Value="{x:Static SystemColors.HighlightBrush}"
/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<EventSetter Event="PreviewMouseDoubleClick" Handler="NameListView_PreviewMouseDoubleClick"/>
</Style>
</ListView.ItemContainerStyle>
<!-- Until NET 4.0 Keygesture's cannot bind to a command, so the inputbindings must be set using static commands or with code behind-->
<ListView.Template>
<!--Template Defining the layout of this treeview-->
<ControlTemplate>
<Grid
Background="{TemplateBinding Background}"
>
<Grid.RowDefinitions>
<RowDefinition
Height="{Binding GraphHeight, Source={x:Static DaedalusGraphViewer:SettingsManager.AppSettings},
Converter={StaticResource GridLengthConverter}}"
/>
<RowDefinition Height="*"/>
<RowDefinition Height="18" />
</Grid.RowDefinitions>
<Border
Grid.ZIndex="1"
Grid.Row="0"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
>
<Grid>
<TextBlock
Foreground="{TemplateBinding Foreground}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Text="Signal Names"
/>
</Grid>
</Border>
<Canvas>
<Line
Grid.ZIndex="2"
x:Name="SelectedItemUnderline"
Stroke="Black"
StrokeThickness="3"
Visibility="Collapsed"
/>
</Canvas>
<ScrollViewer
Grid.ZIndex="1"
x:Name="SignalNameScrollViewer"
Grid.Row="1" Grid.RowSpan="2"
CanContentScroll="False"
VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Visible"
>
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListView.Template>
</ListView>
I had a first chance exception being handled inside the drag operation, so when I fixed that code, it allowed me to drop anywhere in the listview. Basically, if an exception is thrown in the drag handlers, the mouse cursor will display not available to drop and fail drop

wpf itemscontrol items outside of control

I have an own control which derives from itemscontrol with an own template. I am using a Canvas inside the itemscontrol as ItemsPanel. Why f.e. on resize of the window the items also can be outside of the itemscontrol?
Templates:
<Style TargetType="{x:Type local:Dashboard}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Dashboard}">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
The items use this:
<Style TargetType="{x:Type local:Widget}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Widget}">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="2" BorderBrush="Black" Background="WhiteSmoke"
x:Name="Part_Header">
<ContentPresenter ContentSource="Header"/>
</Border>
<Border Grid.Row="1" BorderThickness="2" BorderBrush="Black" Background="WhiteSmoke">
<Grid>
<ContentPresenter />
<ResizeGrip x:Name="Part_Resize"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Cursor="SizeNWSE" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Depending on your alignment and margin settings, resizing a parent can cause children to move outside of a parent's boundaries. The easiest way I've found to check this is to load Blend and resize the parent, watching how contained controls move. By tweaking the anchors in Blend (which changes alignments and margins), you should be able to troubleshoot why they move.

wpf chart legend

How do I enlarge those rectangles ?
I'm using wpf toolkit charts and I've tried to play with the control legend but it didn't helped.
With Blend, in the Objects panel:
Right Click on [PieSeries]
-Edit Additional Templates
-Edit LegendItemStyle
-Edit a Copy
You should get a default style:
<Style x:Key="PieChartLegendItemStyle" TargetType="{x:Type chartingToolkit:LegendItem}">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type chartingToolkit:LegendItem}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal">
<Rectangle Width="8" Height="8" Fill="{Binding Background}" Stroke="{Binding BorderBrush}" StrokeThickness="1" Margin="0,0,3,0" />
<visualizationToolkit:Title Content="{TemplateBinding Content}" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And your control will get a LegendItemStyle
<Charting:PieSeries ItemsSource="{Binding PutYourBindingHere}"
IndependentValueBinding="{Binding Key}" DependentValueBinding="{Binding Value}" IsSelectionEnabled="True" LegendItemStyle="{DynamicResource PieChartLegendItemStyle}">

Resources