I'm struggling with the horizontal fitting of contents when trying to display a UserControl in a ContextMenu, by templating one of its MenuItem:
<ControlTemplate x:Key="MyUserControlMenuItemTemplate" TargetType="{x:Type MenuItem}">
<Grid>
<MyUserControl/>
</Grid>
</ControlTemplate>
<MenuItem x:Key="MyUserControlMenuItem" x:Shared="False" Header="My user control">
<MenuItem Template="{StaticResource MyUserControlMenuItemTemplate}"/>
</MenuItem>
<ContextMenu x:Key="MyUserControlContextMenu" x:Shared="False">
<ContextMenu.ItemsSource>
<CompositeCollection>
<StaticResource ResourceKey="MyUserControlMenuItem"/>
<!-- More stuff here -->
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
This is mostly working, and I'm getting the context menu displayed under the desired circumstances and the UserControl accessible within it, as intended (a different question is whether this is a good design decision). The UserControl is just arranging some controls in a Grid.
The problem is that, depending on the position of the containing window and the actual screen resolution, sometimes the panel containing the templated menu item is not wide enough to hold it completely, and the user control is cut.
How could I get the UserControl to be dynamically resized in order to fit within the horizontal space available in the containing panel?
The UserControl XAML markup is as follows:
<UserControl x:Class="MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Grid.Row="0"
Height="210"
ItemsSource="{Binding ...}"
SelectedItem="{Binding ...}"
SelectionMode="Single">
<ListView.View>
<GridView ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<GridViewColumn DisplayMemberBinding="{Binding ...}" Header="First Name" Width="Auto"/>
<GridViewColumn DisplayMemberBinding="{Binding ...}" Header="Last Name" Width="Auto"/>
<GridViewColumn DisplayMemberBinding="{Binding ...}" Header="Address" Width="Auto"/>
</GridView>
</ListView.View>
</ListView>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Margin" Value="4"/>
<Setter Property="Height" Value="24"/>
<Setter Property="Width" Value="24"/>
</Style>
<Style x:Key="ImageStyle" TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.35"/>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Button x:Name="FirstPageButton" Grid.Column="0" Style="{StaticResource ButtonStyle}">
<Image Source="..." Style="{StaticResource ImageStyle}"/>
</Button>
<Button x:Name="PreviousPageButton" Grid.Column="1" Style="{StaticResource ButtonStyle}">
<Image Source="..." Style="{StaticResource ImageStyle}"/>
</Button>
<Button x:Name="NextPageButton" Grid.Column="2" Style="{StaticResource ButtonStyle}">
<Image Source="..." Style="{StaticResource ImageStyle}"/>
</Button>
<Button x:Name="LastPageButton" Grid.Column="3" Style="{StaticResource ButtonStyle}">
<Image Source="..." Style="{StaticResource ImageStyle}"/>
</Button>
<Button x:Name="OpenButton" Grid.Column="5" Style="{StaticResource ButtonStyle}">
<Image Source="..." Style="{StaticResource ImageStyle}"/>
</Button>
</Grid>
</Grid>
</UserControl>
I don't really think the issue is in the UserControl, though, but I may be well wrong.
Related
I'm trying to create a list with fully functional headers, but I can only seem to get either a list with functional headers and all list view items reduced to textblocks. OR a list view with all the buttons and text fully styled, but without the headers being properly linked. See the image below;
My ListView definition looks like this for both of them:
<ListView ItemsSource="{Binding ScenarioComponents}" Style="{StaticResource ListViewWithHeader}" ItemContainerStyle="{StaticResource ListViewWithHeaderItem}">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto" Header="{Binding NameHeader}" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Width="Auto" Header="{Binding TypeHeader}" DisplayMemberBinding="{Binding Type}"/>
<GridViewColumn Width="Auto" Header="{Binding InfoHeader}"/>
<GridViewColumn Width="Auto" Header="{Binding ExportHeader}"/>
<GridViewColumn Width="Auto" Header="{Binding DeleteHeader}"/>
</GridView>
</ListView.View>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*"/>
<ColumnDefinition Width="1.5*"/>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding Name}" HorizontalAlignment="Left"/>
<Label Grid.Column="1" Content="{Binding Type}" Background="{StaticResource XVROrange}"/>
<Button Grid.Column="2" Style="{StaticResource BorderLessButton}" Command="{Binding MoreInfoCommand}">
<Button.Content>
<Image Source="/Views/Images/cc2_gui_information_default.png"/>
</Button.Content>
</Button>
<Button Grid.Column="3" Style="{StaticResource BorderLessButton}" Command="{Binding ExportCommand}">
<Button.Content>
<Image Source="/Views/Images/cc2_gui_export_default.png"/>
</Button.Content>
</Button>
<Button Grid.Column="4" Style="{StaticResource BorderLessButton}" Command="{Binding DeleteCommand}">
<Button.Content>
<Image Source="/Views/Images/cc2_gui_b_delete.png"/>
</Button.Content>
</Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And the only difference in the styling is that the one with the Headers working uses a GridViewRowPresenter in the ListViewItem like this:
<Style x:Key="ListViewWithHeaderItem" TargetType="ListViewItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Border" Padding="0" Background="Transparent" BorderBrush="{StaticResource XVR70}" BorderThickness="1">
<GridViewRowPresenter Content="{TemplateBinding Content}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And the second one uses the same styling only with a ContentPresenter instead of the GridViewRowPresenter without any embellishments.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Background="Transparent" BorderBrush="{StaticResource Black47}" BorderThickness="0,0,0,0">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
For some reason using the GridViewRowPresenter means every item in my ListView.ItemTemplate's DataTemplate gets turned into a Textblock. And I can't figure out why. I'd really prefer to keep using the GridViewRowPresenter though as this means the headers are bound to the items in the list and scale with them and everything.
Has anyone got any idea how I can style this to work?
Can you put your templates from the ItemTemplate into the GridViewColumns?
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="Auto" Header="{Binding NameHeader}" DisplayMemberBinding="{Binding Name}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<Label Grid.Column="0" Content="{Binding Name}" HorizontalAlignment="Left"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<!-- more columns -->
</GridView.Columns>
</GridView>
</ListView.View>
I have two TextBoxes, two ListBoxes, a Cancel button and an OK button.
Simplifying the problem, I would like to link the color of the Borderbrush of the second ListBox to the IsEnabled property of the OK button.
An alternative would be link that color change to the ListBoxItem background instead of the Listbox border itself.
Is it possible (maybe through Triggers or something)? If so, could you show me the way?
The XAML of the window is as follows:
<Window x:Class="Opt.ExpertSystem.View.WindowPasteRules"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:scroll="clr-namespace:Opt.ExpertSystem.View"
Title="Paste Rules Options" Width="400" Height="300">
<Window.InputBindings>
<KeyBinding Key="Esc" Command="{Binding CancelCommand}" />
</Window.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="100*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="76*" />
</Grid.ColumnDefinitions>
<Label Content="Select Rules to Paste: " Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" HorizontalContentAlignment="Right" Margin="0,0,2,0" Width="Auto"/>
<Grid Grid.Row="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Grid.Resources>
<Style TargetType="ScrollViewer">
<Setter Property="scroll:ScrollSynchronizer.ScrollGroup" Value="Group1" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="50*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Content="Replace" HorizontalAlignment="Stretch" FontWeight="Bold"/>
<TextBox Margin="55,2,2,2" Text="{Binding CopyNameOrigin}" ToolTip="Non-editable field. Represents the text you want to replace." Focusable="False"/>
<Label Content="With" Grid.Column="2" HorizontalAlignment="Stretch" FontWeight="Bold"/>
<TextBox Grid.Column="2" Margin="42,2,2,2" Text="{Binding CopyNameNew, UpdateSourceTrigger=PropertyChanged}" ToolTip="Represents the results of the changes to be made." />
<ListBox ItemsSource="{Binding Path=CopiedRules}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="0" BorderThickness="1" BorderBrush="CornflowerBlue" Grid.IsSharedSizeScope="True" Margin="2,0,2,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<Label Content="{Binding Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Path=PasteRules}" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Column="2" BorderThickness="1" BorderBrush="CornflowerBlue" Margin="2,0,2,10" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" Margin="2,5,2,5" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
<Grid Grid.Row="2" Background="#FFECE9D8" Grid.ColumnSpan="2">
<Button Content="OK" x:Name="btnOK" IsEnabled="{Binding IsValid, UpdateSourceTrigger=PropertyChanged}" Margin="0,6,6,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75" Height="23" Click="btnOK_Click" />
<Button Content="Cancel" x:Name="btnCancel" IsCancel="True" Margin="0,6,90,0" Grid.Row="3" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Top" Width="75" Height="23" />
</Grid>
</Grid>
</Window>
Here's a small example that changes the border brush of a listview based on the IsEnabled property of a button
<StackPanel>
<ListBox Height="100">
<ListBox.Style>
<Style TargetType="ListBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=okButton, Path=IsEnabled}" Value="false">
<Setter Property="BorderBrush" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=okButton, Path=IsEnabled}" Value="true">
<Setter Property="BorderBrush" Value="Blue"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.Style>
</ListBox>
<Button IsEnabled="True" Name="okButton">true</Button>
</StackPanel>
But I would set the availability of the button on the command and not in the XAML, also I would bind the color of the ListView to the IsValid property in the ViewModel instead.
I have a number of buttons on a form (devcomponents ButtonDropDown controls to be precise).
I want to show a tool tip for each that contains a header at the top, an image on the left and a description on the right.
The header needs to be tied to the ButtonDropDown.Header, the image to the ButtonDropDown.Image. I also then need to define the description somewhere.
I've only been using WPF for a few weeks so I've not managed to find any answers via searching, though I have studied a few.
Below is my attempt at creating a template that really doesn't work at all:
<Style TargetType="dcr:ButtonDropDown">
<Setter Property="OverridesDefaultStyle" Value="True"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="dcr:ButtonDropDown">
<ContentControl>
<ContentControl.ToolTip>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Content="{TemplateBinding Header}" FontWeight="Bold" />
<Viewbox Grid.Row="1" Grid.Column="0" Width="64" Height="32" Margin="3">
<ContentControl Content="{TemplateBinding Image}" />
</Viewbox>
<Label Grid.Row="1" Grid.Column="1"
Content="{TemplateBinding ToolTip.Content}" />
</Grid>
</ContentControl.ToolTip>
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I then define a button as follows:
<dcr:ButtonDropDown Header="-X" Command="{Binding MoveCommand}" CommandParameter="xMinus"
ImagePosition="Top" IsEnabled="{Binding UserConfiguration.Move.Visible}"
ToolTip="move x axis down">
<dcr:ButtonDropDown.Image>
<Viewbox Width="32" Height="32" Margin="3">
<ContentControl Content="{StaticResource minusXImage}" />
</Viewbox>
</dcr:ButtonDropDown.Image>
</dcr:ButtonDropDown>
Please could someone give me an idea how to go about this?
I've gone some way to answering this question.
The following style is defined for ToolTip:
<Style TargetType="ToolTip">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Header)}"
FontWeight="Bold" />
<Viewbox Grid.Row="1" Grid.Column="0" Width="64" Height="32" Margin="3">
<ContentControl Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Image)}" />
</Viewbox>
<Label Grid.Row="1" Grid.Column="1"
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.ToolTip)}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I then define a button as above and the ToolTip text and header appear in the ToolTipas required.
The key is the binding:
Content="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ToolTip}},
Path=PlacementTarget.(dcr:ButtonDropDown.Header)}"
Which finds the Tooltip as an ancestor of Label and casts its PlacementTarget into a ButtonDropDown
What doesn't work is the image. This appears in the ToolTip but is removed from the button.
This will also break any other controls' tooltips if they are not ButtonDropDown controls.
I'm beginning to think I'll need to create some custom controls that contain the information I require for the ToolTip for each control.
I am currently doing a page with a form in it in WPF. There are two textboxes and one listbox with a button to add some elements in the listbox. In one mode (edit mode), I want everything to be visible so that the user will be able to edit the textboxes and add elements in the listbox. In the other mode (view mode), I binded the Visibility property so that when in this mode, everything except the listbox appears (and the listbox takes the whole place) so that the user can just see what existing elements are in the listbox.
Now my problem is, in the edit mode I give a Margin="10" margin, but in view mode I would like the listbox to take the full page width/height (so I would like to remove that margin). How would I go to do this?
My XAML (some user controls are encapsulated in a framework that I am using, but it shouldn't affect my question):
<Grid x:Name="MainScope" pres:OneTheme.Theme="Content">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="53*" />
</Grid.RowDefinitions>
<pres:OneContentLayout Mode="List" Grid.Row="3" Margin="10" >
<pres:OneListBox x:Name="ListBox" BorderBrush="{DynamicResource Presentation_ControlBorderBrush}" BorderThickness="1"
ItemsSource="{Binding InterfaceSpecification.IOPoints}"
DeleteItemRequestCommand="{Binding DeleteIOPointCommand}" IsEdited="{Binding IsEditable}" >
<pres:OneListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<vw:IOPointDefinitionView Grid.Column="0" />
<vw:IOPointOtherConnectedElementView Grid.Column="1" Margin="20,0"/>
<pres:OneIcon Grid.Column="2" IconBrush="{DynamicResource Icon_DraggableHandleHorizontal}" Margin="8,0" HorizontalAlignment="Right" Visibility="{Binding ElementName=ListBox, Path=IsEdited, Converter={StaticResource OneBooleanToVisibilityConverter}}" />
</Grid>
</DataTemplate>
</pres:OneListBox.ItemTemplate>
</pres:OneListBox>
</pres:OneContentLayout>
<pres:OneTextBox Watermark="Name..." Text="{Binding InterfaceSpecification.Name}" Margin="85,12,0,0"
AcceptsReturn="False" MaxLines="1" Height="22" VerticalAlignment="Top"
HorizontalAlignment="Left" Width="300" Visibility="{Binding IsEditable, Converter={StaticResource OneBooleanToVisibilityConverter}}" />
<pres:OneTextBox Margin="85,3.999,10,3" Text="{Binding InterfaceSpecification.Description}"
Watermark="Description..." Height="66" Grid.Row="1" Visibility="{Binding IsEditable, Converter={StaticResource OneBooleanToVisibilityConverter}}"/>
<pres:OneToggleButton x:Name="Add_Button" Content="Add IO Point" HorizontalAlignment="Right"
VerticalAlignment="Bottom" Margin="0,0,10,0" Grid.Row="2" Width="115" Height="18"
IsChecked="{Binding ElementName=Add_Popover, Path=IsOpen}"
pres:OneTheme.PresentationMode="Inline" Visibility="{Binding IsEditable, Converter={StaticResource OneBooleanToVisibilityConverter}}" />
...
So you basically want pres:OneContentLayout to have a margin of 0 when IsEditable is false and 10 when it's true, right?
You can use a Trigger in a Style to make that work like this:
<pres:OneContentLayout.Style>
<Style TargetType="{x:Type pres:OneContentLayout}">
<!-- Default margin is 0 -->
<Setter Property="Margin" Value="0" />
<Style.Triggers>
<!-- When in edit-mode make margin 10 -->
<DataTrigger Binding="{Binding IsEditable}" Value="True">
<Setter Property="Margin" Value="10" />
</DataTrigger>
</Style.Triggers>
</Style>
</pres:OneContentLayout.Style>
I am trying to create a WPF window to have a simple expander to extend the datagrid when the user clicks on the More expander button. When the user wants to hide the datagrid, user just has to clik on the Less expander button.
I am also using dock panel to separate header, left, right and footer.
The problems are :
I want to have the less button to be in center before the user
click on the more expander button. When the user clicks on the more
expander button, the less button will be pushed to the left, to show
the datagrid on the right.
How do I change the name of the expander when its closed and
open. Can I do it at the xaml level?
Below is the xaml code:
<Window x:Class="M.SalesWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="SalesWindow" Height="300" Width="300">
<DockPanel>
<StackPanel DockPanel.Dock="Top">
<Label FontSize="28" Content="Sales">
</Label>
</StackPanel>
<StackPanel DockPanel.Dock="Left" Width="auto" HorizontalAlignment="Center">
<Label FontSize="15" Content="Enter Amount" Height="26" Width="168" />
<Separator Width="168" />
</StackPanel>
<StackPanel DockPanel.Dock="Right">
<Expander ExpandDirection="Left" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Expander.Header>
<TextBlock Text="More">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Expander.Header>
<Expander.Content>
<StackPanel>
<DataGrid ItemsSource="{Binding Products}">
</DataGrid>
</StackPanel>
</Expander.Content>
</Expander>
</StackPanel>
</DockPanel>
</Window>
Thank you.
Replace your code with the below code and see the magic. This will also solve your problem of alignment as per your requirement. I have removed the DockPanel as you can achieve the similar result with this piece of code.
<StackPanel>
<StackPanel>
<Label FontSize="28" Content="Sales">
</Label>
</StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" HorizontalAlignment="Center">
<Label FontSize="15" Content="Enter Amount" Height="26" Width="168" />
<Separator Width="168" />
</StackPanel>
<Expander Grid.Column="1" ExpandDirection="Left" HorizontalAlignment="Right" VerticalAlignment="Stretch">
<Expander.Style>
<Style TargetType="Expander">
<Setter Property="IsExpanded" Value="False" />
<Setter Property="Header">
<Setter.Value>
<TextBlock Text="Less">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsExpanded,RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="Header">
<Setter.Value>
<TextBlock Text="More">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-90"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Expander.Style>
<Expander.Content>
<StackPanel>
<DataGrid ItemsSource="{Binding Products}">
</DataGrid>
</StackPanel>
</Expander.Content>
</Expander>
</Grid>
</StackPanel>
The trick lies under the following lines of code.
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>