WPF Border and Header alignment - wpf

Got two problems here in my XAML code.
<Grid Margin="20">
<ListBox x:Name="lbChampToSelect" ItemsSource="{Binding Lst}" HorizontalContentAlignment="Stretch" Grid.IsSharedSizeScope="True">
<Border Background="FloralWhite" BorderBrush="Silver" BorderThickness="1" CornerRadius="3,3,3,3">
<ListBox.Template>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Grid Margin="5,2" DockPanel.Dock="Top" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" SharedSizeGroup="Col1"></ColumnDefinition>
<ColumnDefinition Width="100" SharedSizeGroup="Col1"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Column="0">Libellé</Label>
<CheckBox IsChecked="False" Grid.Column="1"/>
</Grid>
<ItemsPresenter></ItemsPresenter>
</DockPanel>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="5,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" SharedSizeGroup="Col1"/>
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock Margin="0,0,10,0" Text="{Binding Libelle }" Grid.Column="0" />
<CheckBox IsChecked="False" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</Border>
</ListBox>
</Grid>
First : whatever I try, I cannot align the header and the columns containing checkboxes (with a text labelling the checkbox it's worth). At the end, the header checkbox is supposed to check all the subsequents.
Second : I simply try to have a border on my entire listbox including the header but I got a xaml error saying the member Template is not accessible or does not exists.
Thx for your answers.

Otherwise, by using a ListView you can have header for items :
<ListView Margin="10" x:Name="lbChampToSelect" ItemsSource="{Binding Lst}" HorizontalContentAlignment="Stretch" Grid.IsSharedSizeScope="True" BorderBrush="Silver"
BorderThickness="1">
<ListView.Resources>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
<Style TargetType="CheckBox" BasedOn="{StaticResource {x:Type CheckBox}}">
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Libelle" Width="120" DisplayMemberBinding="{Binding Libelle}" />
<GridViewColumn Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{ Binding IsChecked}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumn.Header>
<CheckBox/>
</GridViewColumn.Header>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>

I'll start with the second question:
Your Border should be within the ControlTemplate (given I have guessed right how you want it to be).
<ControlTemplate>
<Border Background="FloralWhite" BorderBrush="Silver" BorderThickness="1" CornerRadius="3,3,3,3">
Now on to the first question: There are many things that affect the layouting of the items in the ListBox. Here's the method I would use to solve the problem.
Remove margins from your Grids, I would set them to 0, at least for now. You can add layouting later, when you know what affects what.
Download Snoop
Start your application and start snooping it
Find your controls in the hierarchy, and try modifying the margin/padding values. That way you'll see what affects layouting.
Apply new values in code.

Related

Adjust height/position of multiple listviews so that content is aligned

I'm designing an application where I need to position multiple ListViews in a way that the content is aligned like this (simplified):
What I have:
The outer layout is a Grid (black)
The ListView (grey) on the left has a small header
The ListViews (grey) on the right are generated in an ItemsControl and have a fairly large header (vertical text). Also, they are part of a UserControl with additional content above them (not shown here)
What I want:
The contents (red) of all ListViews should be aligned and start at the same height (blue line)
I DON'T want to set the headers (green) to have the same height, because that would waste much space due to the large height difference.
The only solution I can think of is to calculate the height of all elements above the ListViews and the height of the headers, and then change the height of the upper Grid row so that the contents start at the same height. But that seems rather tedious, error prone and clumsy to me.
Is there a more elegant solution, maybe involving SharedGroupSize or binding the height property?
XAML for the overall layout:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<local:SomeControl1 x:Name="generalSettingsControl" Grid.Column="0" Grid.Row="0" />
<ListView ItemsSource="{Binding FirstList}">
<ListView.View>
<GridView>
<GridViewColumn Header="Name"
DisplayMemberBinding="{Binding CombinedName}" />
<GridViewColumn Header="ID"
DisplayMemberBinding="{Binding ID}" />
</GridView>
</ListView.View>
</ListView>
<ItemsControl Grid.Column="1" Grid.RowSpan="2" ItemsSource="{Binding Samples}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:ListViewUserControl DataContext="{Binding }" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
XAML for the ListViews in the ItemsControl :
<UserControl.Resources>
<Style x:Key="verticalGridViewColumnHeader" TargetType="GridViewColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock TextWrapping="Wrap" Text="{Binding}" FontWeight="Bold" Width="60"
VerticalAlignment="Center" TextAlignment="Center" HorizontalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="270" />
</TextBlock.LayoutTransform>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="10" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Text="Placeholder (TODO)" Grid.Column="0" />
<ListView x:Name="lvMeasurementsEdit"
ItemsSource="{Binding Measurements}"
Grid.Column="0"
Grid.Row="2">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn Header="Value 1" DisplayMemberBinding="{Binding Value1}"
HeaderContainerStyle="{StaticResource verticalGridViewColumnHeader}" Width="Auto" />
<GridViewColumn Header="Value 2" DisplayMemberBinding="{Binding Value2}"
HeaderContainerStyle="{StaticResource verticalGridViewColumnHeader}" Width="Auto" />
</GridView>
</ListView.View>
</ListView>
</Grid>

wpf ListBox looks like datagrid?

I have a listbox control in my app.
I want to change his style to being look like to Datagrid (borders, columns, row...).
I don't want to using stantard datagrid - because its control cannot binding itemtemplte.
I trying to do it:
<ListBox
ItemsSource="{Binding Items}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Name="listBox1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border BorderThickness="1" BorderBrush="Black">
<TextBlock Text="{Binding Id}" Margin="5"/>
</Border>
<Border BorderThickness="1" BorderBrush="Black">
<TextBlock Text="{Binding Name}" Margin="5"/>
</Border>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
But it not looking good - as following:
it what i want to achieve:
Using Grid.IsSharedSizeScope
result
i believe you want the columns to be re-sized based on your string length, so Grid.IsSharedSizeScope is your choice here
example xaml
<ListBox ItemsSource="{Binding Items}"
Grid.IsSharedSizeScope="True">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="name" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border BorderThickness="1"
BorderBrush="Black">
<TextBlock Text="{Binding Name}"
Margin="5" />
</Border>
<Border BorderThickness="1"
Grid.Column="1"
BorderBrush="Black">
<TextBlock Text="{Binding Id}"
Margin="5" />
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
if you move SharedSizeGroup to id like below
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition SharedSizeGroup="id" />
</Grid.ColumnDefinitions>
result
Using ListView with GridView
You have an option to use list view with grid view which will have same appearance as grid with flexibility of list
eg
<ListView ItemsSource="{Binding SourceItems}">
<ListView.View>
<GridView>
<GridViewColumn Header="Column1"
DisplayMemberBinding="{Binding Column1}" />
<GridViewColumn Header="Column2"
DisplayMemberBinding="{Binding Column2}" />
</GridView>
</ListView.View>
</ListView>
GridViewColumn offers you to modify CellTemplate, HeaderTemplate, HeaderContainerStyle, HeaderStringFormat etc.
I am sure you can achieve this using a grid control (It supports binding and everything else)
To fix your problem, you will have to give fixed widths to both your borders inside your stackpanel then your listbox items will look like a grid control.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border Width="150" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="{Binding Id}" Margin="5"/>
</Border>
<Border Width="50" BorderThickness="1" BorderBrush="Black">
<TextBlock Text="{Binding Name}" Margin="5"/>
</Border>
</StackPanel>
Please let us know what problem you are having with GridControl and maybe we can fix that as well
Edit. If you were using a DataGrid your template would look like
<DataGrid ItemsSource="{Binding Items}" AutoGenerateColumns="False" HeadersVisibility="None">
<DataGrid.Columns>
<DataGridTemplateColumn Header="" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text={Binding Id}/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text={Binding Name}/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Please note that I have set HeaderVisibility to false so that it doesnt look like a datagrid but instead looks like a list

Is there any way to add checkbox to all column headers inside datagrid in wpf

I have listbox containing datagrid that is binded to a datatable in the following way:
In code behind:
listBox1.Items.Add(dt1);
Here dt is the table name.
In Xaml:
<ListBox Grid.Row="0" MinHeight="305" HorizontalAlignment="Stretch" Name="listBox1" VerticalAlignment="Stretch" MinWidth="537" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel MinHeight="80" MinWidth="500" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<DataGrid Grid.Column="1" AutoGenerateColumns="True" MinHeight="75" HorizontalAlignment="Center" Name="dataGrid1" VerticalAlignment="Stretch" MinWidth="470" MaxWidth="900" ItemsSource="{Binding}" IsReadOnly="True" >
</DataGrid>
<CheckBox Grid.Column="0" Height="35" Width="25" Name="IsDone" HorizontalAlignment="Right" VerticalAlignment="Center"/>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I want to add check box to all column headers present in datagrid. Can you please suggest me how to add checkboxes to all column headers present inside datagrid in Wpf
Thanks in advance
You can define ColumnHeaderStyle for your DataGrid and in that set the ContentTemplate to have checkboxes for all headers like this:
<DataGrid>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox Content="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>

Make a grid's width in ListView.ItemTemplate the same width as the ListViewItem

What I'm trying to do is to make a Grid inside of the ItemTemplate expand to the width of the ListViewItem and not to just the space it needs. This is how I DON'T want it to look like:
Basically I want the red grid to be the width of the blue rectangle (which is the selected item). This is my XAML:
<ListView ItemsSource="{Binding}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Background="Red">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding FirstName}" />
<TextBlock Grid.Column="1" Text="{Binding LastName}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Thanks in advance!
Do the following:
<ListView ItemsSource="{Binding}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
..

What stops the tab?

I have the following xaml:
<ListBox ItemsSource="{Binding Path=ItemProperties.GeneralProperties}" Grid.Row="1"
Margin="0" Style="{StaticResource ListBoxStyle1}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180" />
<ColumnDefinition Width="320" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Column="0" />
<ContentPresenter Content="{Binding Converter={StaticResource PropertyInput}}" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
where the ContentPresenter contains a TextBox, or a ComboBox, or a CheckBox.
To switch between the controls I need twice press the tab. Why???
I've already tried to comment the whole first column, without the TextBlock, unsuccessfully.
This worked for me for a DataGrid (which has a similar templating system).
<UserControl.Resources>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
</Style>
</UserControl.Resources>
Then anything which is a TabStop within the datagrid would work as a tabstop, but nothing else. Sorry I'm not sure what the equivalent code is for ListBox - but you may be able to figure it out from this.

Resources