Width of the expander header affects the scrollviewer outside - c#

The below is my code
<Window x:Class="ScrollTester.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>
Here I have set the datatemplate for the header of the expander I am using inside the stack Panel
<DataTemplate x:Key="titleText">
<Border Background="Green" Height="24">
<TextBlock Text="{Binding}"
Width="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type Expander}},
Path=ActualWidth}"/>
</Border>
</DataTemplate>
<Style TargetType="{x:Type Expander}">
<Setter Property="Margin" Value="1,3"/>
<Setter Property="BorderBrush" Value="Gray"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="HeaderTemplate" Value="{StaticResource titleText}"/>
</Style>
</Window.Resources>
I have a scroll viewer for the stack panel
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel>
<Expander IsExpanded="True" x:Name="general" Header="General">
<StackPanel Orientation="Horizontal">
<GroupBox Header="Mode Control">
<StackPanel>
<CheckBox Content="RESET"/>
<CheckBox Content="MAKEUP" IsChecked="True"/>
<CheckBox Content="POWERDOWN"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Mode Control">
<StackPanel>
<CheckBox Content="RESET"/>
<CheckBox Content="MAKEUP" IsChecked="True"/>
<CheckBox Content="POWERDOWN"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Mode Control">
<StackPanel>
<CheckBox Content="RESET"/>
<CheckBox Content="MAKEUP" IsChecked="True"/>
<CheckBox Content="POWERDOWN"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Mode Control">
<StackPanel>
<CheckBox Content="RESET"/>
<CheckBox Content="MAKEUP" IsChecked="True"/>
<CheckBox Content="POWERDOWN"/>
</StackPanel>
</GroupBox>
<GroupBox Header="Mode Control">
<StackPanel>
<CheckBox Content="RESET"/>
<CheckBox Content="MAKEUP" IsChecked="True"/>
<CheckBox Content="POWERDOWN"/>
</StackPanel>
</GroupBox>
</StackPanel>
</Expander>
</StackPanel>
</ScrollViewer>
The problem here is the scroll bar is not working even when the stack panel's width is more.
I can understand why it happens,because of setting the width of the expander to its parent,so scroll bar is not working
But I want both the scroll bar working and enabled as well as the datatemplate with style for the header
Any one can give solution?

What you are trying to do won't work because the width of the expander's header also includes the button used to expand and collapse the control.
Think of it this way: the header area of the control contains two elements side-by-side, the expand/collapse button and the header "content". You are binding the width of the header content part (your Border element) to the width of the expander control, but this doesn't subtract the width of the expand/collapse button. Hence your layout breaks.
If the header content part sat behind the expand/collapse button then your approach would work, but unfortunately that's not how the default Expander control template is designed.
I'm just guessing, but it looks to me like you are simply trying to set the background colour of the expander. Unfortunately, again due to the default control template, this isn't possible:
if you set the Background property of the expander, this will change the colour of the header, but it will also change the colour of the content area which probably isn't what you want
putting another element in the header (such as your Border) and attempting to get it to "stretch" to the width of the control (by setting the HorizontalContentAlignment property to Stretch) won't work either, as the element into which the header is placed is hard-coded in the control template to be left-aligned.
As far as I know, the only way of accomplishing what you want is to write your own control template for the expander and use that instead. You should be able to find some examples of this here on SO or by Googling.

Related

C# WPF DataGrid Column Header fitting TextBox into width

I've a DataGrid in my C# WPF application and styled the Columns Header with a Label/TextBlock and a TextBox as an instant filter beneath of it.
My target is to fit the width of the TextBox into the width of the DataGridColumn, but I didn't found an acceptable way for me.
Currently I'm using a Viewbox, but this crashes all size measurements of the elements in the header.
Here is an example what it looks like with the Viewbox:
As you can see, I've either a too big TextBox and FontSize or a too small TextBox.
My currently code looks like that:
<DataGridTemplateColumn.Header>
<Viewbox StretchDirection="DownOnly">
<StackPanel>
<TextBlock Text="Mitarbeiter"/>
<TextBox x:Name="txtInstantSearchPersonio" HorizontalAlignment="Stretch" TextChanged="evh_InstantFilterChanged"/>
</StackPanel>
</Viewbox>
</DataGridTemplateColumn.Header>
Is there a way to fit the TextBox into full wifth of the column but don't stretch the height or fontsize?
You could use a Style for DataGridColumnHeader to fit the Textbox inside of a column
<DataGridTemplateColumn Width="200">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.Header>
<StackPanel>
<TextBlock Text="Mitarbeiter"/>
<TextBox x:Name="txtInstantSearchPersonio" HorizontalAlignment="Stretch" TextChanged="evh_InstantFilterChanged"/>
</StackPanel>
</DataGridTemplateColumn.Header>
Tried by desperation results in an really simple solution.
I put both elements into a StackPanel:
<DataGridTemplateColumn.Header>
<StackPanel>
<TextBlock Margin="0" Padding="0" Text="Mitarbeiter"/>
<TextBox HorizontalAlignment="Stretch" TextChanged="evh_InstantFilterChanged"/>
</StackPanel>
</DataGridTemplateColumn.Header>
and set the DataGrid.ColumnHeaderStyle simply to this:
<Style x:Key="style_DataGridColumnHeader" TargetType="DataGridColumnHeader">
<Style.Setters>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style.Setters>
</Style>
Works fine for me, the TextBox has always full width of the column header.

WPF Dockpanel extending beyond width of parent

I am attempting to create a dock panel inside of a list view data template that takes up all of the available width of its parent tab control. I started by basing my XAML off of this question and thus came up with this:
<TabControl x:Name="tabControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TabItem Header="Clipboard Buffer">
<ListView Name="clipboardListView" ScrollViewer.CanContentScroll="True">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="Black" CornerRadius="2,2,2,2">
<DockPanel Background="AliceBlue" Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}">
<TextBlock Text="{Binding Text}" DockPanel.Dock="Top" />
</DockPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</TabItem>
...
This almost works, however the dock panel always seems to be just a little bit wider than the space available in the tab control as you can see here.
I can use the scroll bar to move over and see the end of my dockpanel as one would expect...
However, if I attempt to re-size the form, the dockpanel remains slightly larger than the amount of space available in the tab control.
What am I missing here? How can I make my dock panel stay within the width of its parent tab control?
Try this:
<TabControl x:Name="tabControl" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TabItem Header="Clipboard Buffer">
<ListView Name="clipboardListView" ScrollViewer.CanContentScroll="True" HorizontalContentAlignment="Stretch">
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderThickness="2" BorderBrush="Black" CornerRadius="2,2,2,2" >
<DockPanel Background="AliceBlue" >
<TextBlock Text="asdfasdkfhkasdfkasdgfkjhdgfkuwegyfkwegfbkuweyfuksyadukfykweugbyfu" DockPanel.Dock="Top" />
</DockPanel>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</TabItem>
</TabControl>
Note the HorizontalContentAlignment="Stretch" in the ListView
Your DockPanel is nested into a Border element:
<Border BorderThickness="2" BorderBrush="Black" CornerRadius="2,2,2,2">
<DockPanel Background="AliceBlue" Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}">
The Border occupies some width of its own - it has a border thickness of 2, so it is 4 pixels wider than its content.
The content of the Border is your DockPanel - and you have bound its width to the actual width of the enclosing TabControl. As a result, the aforementioned Border will always be a bit wider than the enclosing TabControl.
For a start, you could try and bind the width of the Border rather than that of the DockPanel. This should help to some extent, although I am not completely sure the TabControl doesn't require some extra inner space for its page contents.
It's most likely caused by this line in your DockPanel XAML:
Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}}
Your setting the Width to the ActualWidth of the TabControl, without taking into account any Padding or Margin on the Children.
You need to check if the TabControl, TabItem or ListView have any padding or margins, then take this off too. (Don't forget the 2pixel border!)

WPF Binding TextBox width to grid column within a list box

I'm trying to build a simple (in terms of design) screen which will allow users to enter multiple rows of data.
The format of the screen is 4 columns (TextBox, TextBox, ComboBox, TextBox), with new rows added dynamically.
I have tried 2 approaches initially - one using a DataGrid, and one using a ListView.
The DataGrid caused many headaches with items retaining focus when they were clicked out of, and the ListView prevented me from being able to consistently access the underlying cell, instead returning the bound data object represented by the row.
My current approach uses a custom component which represents a row, and contains the 3 TextBox objects, and one ComboBox object.
One or more of these objects are displayed in a ListBox.
This approach allows for handling events more consistently, but is visually less straightforward to get working.
Currently, when a row is displayed, the first 3 columns in the grid (which have an explicitly defined width) display fine, but the textbox in the final column does not expand to fill the available width.
The relevant code for the panel:
<DockPanel LastChildFill="True" Name="basePanel">
<Grid x:Name="baseGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" />
<ColumnDefinition Width="60"></ColumnDefinition>
<ColumnDefinition Width="55"></ColumnDefinition>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox Name="txtYear" Grid.Column="0" Style="{StaticResource txtComponentStyle}" Text="{Binding Path=RatingYear, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<TextBox Name="txtArrears" Grid.Column="1" Style="{StaticResource txtComponentStyle}" Text="{Binding Path=ArrearsAmount, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<ComboBox Name="cmbChangeCode" Grid.Column="2" ItemsSource="{Binding Path=ChangeCodes, Mode=OneTime}" SelectedItem="{Binding Path=ChangeCode}" />
<TextBox Name="txtComments" Grid.Column="3" Style="{StaticResource txtComponentStyle}" Text="{Binding Path=Comments, ValidatesOnDataErrors=True,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Stretch" />
</Grid>
</DockPanel>
When I select a row in the ListBox, I can see that the object itself fills the entire width, yet the text box in the final column only expands to fit the content.
Setting the width in the column definition to * should (as I understand it) cause the column to expand to fille the available space, and setting the HorizontalAlignment property on the textbox to Stretch should cause the text box to fill the column.
The code below creates the ListBox.
<UserControl.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="0.5" Margin="1">
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch" Background="DarkSlateBlue">
<Controls:ArrearsListEntry />
</DockPanel>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<DockPanel LastChildFill="True" Background="Red">
<ListBox IsSynchronizedWithCurrentItem="True" Name="lstRowData" ItemsSource="{Binding Path=Rows}" />
</DockPanel>
Is there a way to bind the width of the text box to the actual width of the column, or a property which will cause the text box to automatically expand to the available width?
The ListBoxItem's Content is left aligned by default. Add a Setter for the HorizontalContentAlignment to your ListBoxItem Style:
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ContentTemplate">
...
</Setter>
</Style>

Treeview is clipping my items

I've got following code. Why are my items always clipped after about 70px
<sdk:HierarchicalDataTemplate x:Key="OptionsTemplate">
<CheckBox IsTabStop="False" Content="{Binding EnumValue}" IsChecked="{Binding IsSelected, Mode=TwoWay}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="EnumOptionsTemplate" ItemsSource="{Binding Values}" ItemTemplate="{StaticResource OptionsTemplate}">
<TextBlock Text="{Binding EnumType}"/>
</sdk:HierarchicalDataTemplate>
<sdk:TreeView x:Name="FilterTreeView" ItemsSource="{Binding GeoObjectFilter}" ItemTemplate="{StaticResource EnumOptionsTemplate}">
<sdk:TreeView.Template>
<ControlTemplate TargetType="sdk:TreeView">
<StackPanel Background="Transparent">
<ItemsPresenter x:Name="TreeItems" />
</StackPanel>
</ControlTemplate>
</sdk:TreeView.Template>
</sdk:TreeView>
Thanks in advance!
Ho yes i had same issue when redefining the TreeView Template. By the way, i'm not sure you need to, since StackPanel is the Default Template. I got my (wrappanel) template to work by setting a style for ItemsPanel rather than redifining it. And i had to define some width also. Seems the only way to make the Treeview to scale is to bind the width.
See the answer i made to my question here :
https://stackoverflow.com/a/8802718/856501

Listbox item that stretches to width of listbox BUT not past the width

I have a listbox that I want to take up the width of my window, and the list box items will stretch to the size of the listbox.
Each listbox item will be a datatemplate that has about 150 width for information and the remaining size to be a textbox for a description. I want the description texbox to stretch to remaining available size. So here is example xaml that I thought would create this layout:
<Window x:Class="test.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">
<Grid>
<ListBox Margin="20,20,20,20" ItemsSource="{Binding Path=List}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="AliceBlue"
BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Width="20"
Content="Test" />
<ComboBox Width="130" />
<TextBox Grid.Column="1"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch" />
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
However, when I type in the textbox and the text width goes past the width of the listbox, the listbox item keeps growing and the horizontal scroll bar shows up.
What I want to achieve is the max width of the textbox to go just up to the listbox and not grow wider. Anyone know how I can achieve this layout?
Try adding ScrollViewer.HorizontalScrollBarVisibility="Disabled" to ListBox, it worked for me.
The problem is that your Listbox contains a scrollviewer, which means that its children can have any size they want, the scroll viewer will take care of that. Your ColumnDefinition practically says "Use all the unlimited space we have".
One solution that comes to my mind would be to bind the Grids Width to the ListBox ActualWidth
Width="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}, Path=ActualWidth}"
but propably better is Dmitrys solution.

Categories