Confused wpf grid behaviour in DataTemplate - c#

I am confused about the Grid's behaviour inside a ContentTemplate:
I want to style my ListView:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ArticleID}"
Grid.Column="0"
/>
<TextBlock Text="{Binding ArticleName}"
Grid.Column="1"
/>
<Button Command="{Binding DataContext.RemoveComponentFromVehicle, RelativeSource={RelativeSource AncestorType=Grid}}"
Grid.Column="2"
>
<Button.Content>
<StackPanel Style="{StaticResource IconTextCombo}">
<Image Source="{StaticResource ComponentToVehicle_Delete}"/>
</StackPanel>
</Button.Content>
</Button>
</Grid>
As you can see, I want to make sure that my buttons align right on the right side because the ArticleID and Name length can vary.
The buttons aren't align as I want and expect. I have a test project:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBox Text="Foo"
Grid.Column="0"/>
<TextBox Text="Bar"
Grid.Column="1"/>
<Button Content="DELETE"
Grid.Column="2"/>
<TextBox Text="Hello World"
Grid.Column="0"
Grid.Row="1"/>
<TextBox Text="LONG TEXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT"
Grid.Row="1"
Grid.Column="1"/>
<Button Content="DELETE"
Grid.Row="1"
Grid.Column="2"/>
</Grid>
In this 'hardcoded' version every aligns as I want... I don't know why my grid is so weird in the Template. Can someone help me?
Thanks in advance!

Here is the solution after working around:
<ListView DockPanel.Dock="Right"
ItemsSource="{Binding}"
SelectedItem="{Binding }"
Name="lvMain"
HorizontalContentAlignment="Stretch"
>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition />
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ArticleID}"
Grid.Column="0"
/>
<TextBlock Text="{Binding ArticleName}"
Grid.Column="1"
/>
<Button Command="{Binding }"
Grid.Column="2"
>
<Button.Content>
<StackPanel Style="{StaticResource IconTextCombo}">
<Image Source="{StaticResource img}"/>
</StackPanel>
</Button.Content>
</Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I have tested it with ListBox and ListView... It works for both of them as I want now!
Thanks to all helpers!

you need to use the SharedSizeGroup property on your grid in your template. It works in your hardcoded example because all your elements sit inside the same grid. Once you place them inside a ListBox every item has its own grid and is unaware of the other grids.
Setting this property will make sure all these columns have the same size regardless which grid they are in.
your Grid.ColumnsDefinitions should look like this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto" SharedSizeGroup="ColumnA"/>
<ColumnDefinition Width="auto" SharedSizeGroup="ColumnB"/>
<ColumnDefinition Width="auto" SharedSizeGroup="ButtonsColumn"/>
</Grid.ColumnDefinitions>
You should also use ItemTemplate meaning:
<ListBox>
<ListBox.ItemTemplate>
*****Your Posted Code ************
</ListBox.ItemTemplate>
</ListBox>

Related

ListView in UWP

I am trying to Align my ListView items in dynamic way without setting explicitly Width for them. The problem i am getting is aligning them the attribute name that is above them. i.e attribute Name should have Coke below it, Quantity should have Integer value number and Subtotal should have floating points below it.
if i resize my Windows the ListView should also change with the respective attribute name but it doesn't. I have tried RelativePanel, ListBox for them but nothing works without explicity giving a width which i want it to be dynamic.
<Grid Grid.Column="2" Margin="5,0,5,0">
<ScrollViewer VerticalScrollBarVisibility="Hidden">
<StackPanel>
<TextBlock Style="{StaticResource MyTextBlock1}" FontSize="20" HorizontalAlignment="Center" Margin="0,0,0,10">Order Summary</TextBlock>
<RelativePanel>
<TextBlock Name="ItemName" Style="{StaticResource MyTextBlock1}" FontSize="12">Name</TextBlock>
<TextBlock Name="ItemPrice" Style="{StaticResource MyTextBlock1}" FontSize="12" RelativePanel.AlignRightWithPanel="True">SubTotal</TextBlock>
<TextBlock Name="ItemQuantity" Style="{StaticResource MyTextBlock1}" Margin="0,0,10,0" FontSize="12" RelativePanel.LeftOf="ItemPrice">Quantity</TextBlock>
</RelativePanel>
<ListView ItemsSource="{x:Bind dumbList}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Dumb">
<Grid Width="200">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind name}"/>
<TextBlock Text="{x:Bind id}" Grid.Column="1"/>
<TextBlock Name="Quatity" Text="{x:Bind price}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
CLICK HERE!! for the image
Edit:
You can create one item with the DataTemplate layout above the listview.
To avoid setting explicitly the Width, you can set the HorizontalAlignment to Stretch (similiar to Android XML fill_parent) and use Margin.
Example:
<Grid
HorizontalAlignment="Stretch"
Margin="12,12,12,12"
Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Name"/>
<TextBlock Text="Quantity" Grid.Column="1"/>
<TextBlock Text="SubTotal" Grid.Column="2"/>
</Grid>
<ListView ItemsSource="{x:Bind dumbList}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Dumb">
<Grid
HorizontalAlignment="Stretch"
Margin="12,12,12,12"
Height="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{x:Bind name}"/>
<TextBlock Text="{x:Bind id}" Grid.Column="1"/>
<TextBlock Name="Quatity" Text="{x:Bind price}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Your column definitions should be percentages, not whole values.
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".8*"/>
<ColumnDefinition Width=".1*"/>
<ColumnDefinition Width=".1*"/>
</Grid.ColumnDefinitions>
.8 = 80% .1 = 10% .1 = 10% Total = 100%
Your definitions are:
3 = 300% 1 = 100% 1 = 100% Total = 500% !!

Align TextBlock in Button / StackPanel correctly

I try to align the TextBlocks to the left.
The button should take the rest of the area (Up to the picture).
How can I do this?
This is a UWP / C# App.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid VerticalAlignment="Center" HorizontalAlignment="Left">
<Button Background="Transparent" HorizontalAlignment="Stretch">
<StackPanel HorizontalAlignment="Left">
<TextBlock x:Name="TextBlock1" TextWrapping="Wrap" Text="Name1"/>
<TextBlock x:Name="TextBlock2" TextWrapping="Wrap" Text="Name2" />
</StackPanel>
</Button>
</Grid>
<StackPanel Grid.Column="1" Grid.Row="0" HorizontalAlignment="Right">
<Button Height="50" Width="50" Background="Transparent" Click="Button_Click">
<Image x:Name="ImageFavorit" Source="/Assets/Stern/VGrau64.png"/>
</Button>
</StackPanel>
</Grid>
Firstly you should replace your ColumnDefinitions to this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
And secondly remove HorizontalAlignment="Left" from your Grid then you can achieve to what you want:
<Grid VerticalAlignment="Center">
<Button Background="Transparent" HorizontalAlignment="Stretch">
...
Also it seems that you need to set VerticalAlignment="Center" of your StackPanel too:
<StackPanel Grid.Column="1" Grid.Row="0"
HorizontalAlignment="Right" VerticalAlignment="Center">
Update: Based on your comment that you want the text on the left side Set the HorizontalContentAlignment="Left" of the Button:
<Button Background="Transparent" HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left">

Contents of grid are in wrong column

I have this XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<ListView Grid.Column="1" x:Name="layers" Grid.ColumnSpan="1">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Height="100" Width="100" Margin="5"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Grid.Column="2" Grid.ColumnSpan="2">
<Button Height="20" Content="Add layer" Click="aL_Click" HorizontalAlignment="Stretch" Width="Auto"/>
<Button Height="20" Content="Add static layer" Click="aSL_Click" HorizontalAlignment="Stretch" Width="Auto"/>
</StackPanel>
</Grid>
As you can see, ListView is in column 1 of Grid and the StackPanel is in column 2 of Grid. But when I run this and add Image to ListView, the ListView (and Image) are showing in column 2 of Grid, after StackPanel.
What is wrong and how do I fix it?
I just done what I want this way:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<ListView Grid.Column="0" x:Name="layers">
<ListView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Height="100" Width="100" Margin="5"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackPanel Grid.Column="1">
<Button Height="20" Content="Add layer" Click="aL_Click" HorizontalAlignment="Stretch" Width="Auto"/>
<Button Height="20" Content="Add static layer" Click="aSL_Click" HorizontalAlignment="Stretch" Width="Auto"/>
</StackPanel>
</Grid>
Comment from Clemens helped me.
First column is column "0" and not "1".
There is no sense for expression Grid.ColumnSpan="1" because it is default value as well as Grid.Column="0".

WPF trigger event by clicking on specified content of SelectedItem in ListBox

I have template for ListBoxItems that contains 3 columns. Each item is represented by picture-text-picture. Is there some posibillity how to trigger event (for example PreviewMouseLeftButtonDown) only by clicking on third column in ListBoxItem (not enywhere else on item).
I know how to trigger it by clicking on whole ListBoxItem, but i need it to trigger only when clicked on the last column (picture). Thanks.
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,4,0,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image Source="images/showFile.png" Grid.Column="0" Height="16" Width="16"/>
<TextBlock Text="{Binding Name}" Grid.Column="1"/>
<Image Source="images/delete.png" Grid.Column="2" Height="16" Width="16"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
I tried proposed solution and it works. Thanks.
You can set the event listener only for the component you want:
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,4,0,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Image Source="images/showFile.png" Grid.Column="0" Height="16" Width="16"/>
<TextBlock Text="{Binding Name}" Grid.Column="1"/>
<Image Source="images/delete.png" Grid.Column="2" Height="16" Width="16" PreviewMouseLeftButtonDown="OnPreviewMouseLeftButtonDown"/>
</Grid>
</DataTemplate>

WPF - width issue with IsSharedSizeScope "true" and three columns

Simple code:
<ItemsControl Grid.IsSharedSizeScope="True" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="firstColumn" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="splitterColumn" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="lastColumn" Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Key}"/>
<GridSplitter Width="5" Grid.Column="1" />
<TextBlock Text="{Binding Path=Value}" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Problem is occured with lastColumn, width of it is not 100%. I try to set HorizontalAlignment="Stretch" for the all grids but it didn't help.
Width of lastColumn must be 100%. How to resolve this issue?
You don't need to include SharedSizeGroup on every column. In this case, if your first and second columns are sharing a size, you should be able to get your desired behaviour by omitting the property on the last column. There should always be the same amount of space for the last column, if the first two columns are sharing sizes:
<Grid Width="300" Height="30" Background="Red">
<Grid Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="firstColumn" Width="Auto"/>
<ColumnDefinition SharedSizeGroup="splitterColumn" Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBox Text="1" Grid.Column="0"/>
<GridSplitter Width="5" Grid.Column="1"/>
<TextBox Text="Test" Grid.Column="2" />
</Grid>
</Grid>
Edit: This is essentially the problem encountered here: Grid.IsSharedScopeSize incompatible with * columns in WPF Grid
Further edit: You've changed to an ItemsControl now, but the same should still apply.

Categories