How to additional control to ItemsControl - c#

I am building out an ItemsControl that holds Grid elements. Each time an item is added to an ObservableCollection, a new Grid control is created in the ItemsControl. Right now I have some margin between each Grid control but I want to have a TextBox between each control but I am unable to add it appropriately.
If my Grids look like this in the item control
----------------
----------------
I would want the text box here.
----------------
----------------
And here
----------------
----------------
As of now, this is my ItemsControl:
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1" Grid.ColumnSpan="4">
<ItemsControl Grid.Row="1" Grid.ColumnSpan="3" ItemsSource="{Binding StudentsInClassCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Grid.Row="1" Grid.ColumnSpan="3" Margin="5, 0, 15, 50" Height="70">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Grid Grid.Column="1">
<Border BorderThickness="1" BorderBrush="{Binding StudentMemberColor}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"/>
<ColumnDefinition Width="80"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<dxe:TextEdit Grid.Column="1" Margin="5, 5, 5, 5" Width="50" Height="50" HorizontalContentAlignment="Center"
FontFamily="Helvetica" FontWeight="Thin" FontSize="16"
Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Border>
</Grid>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>

Related

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>

Confused wpf grid behaviour in DataTemplate

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>

Grid covers another on resizing in WPF

In a GroupBox I have two grids: the 1st one contains can contain lots of textboxes so that I added a ScrollViewer, the 2nd one contains action buttons that must allways be visible.
A 2nd GroupBox above has an Expander and the problem is that when it is expanded and the 1st grid has enough elements, it covers the 2nd grid with buttons. How can I fix this?
Here my code:
<Window x:Class="ControlOverlayBug.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="269" Width="454">
<DockPanel Background="LightGray" SnapsToDevicePixels="True">
<GroupBox DockPanel.Dock="Top" Header="Simulation Parameters">
<DockPanel>
<Expander DockPanel.Dock="Bottom" x:Name="AlgoParams" Header="Change Us...">
<Grid x:Name="parameterGrid">
<DataGrid
RowHeaderWidth="0"
ItemsSource="{Binding AlgoParameters}"
AutoGenerateColumns="False"
GridLinesVisibility="None"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="1*" IsReadOnly="True"/>
<DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="1*"/>
<DataGridTextColumn Header="Value" Binding="{Binding Value}" Width="1*"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Expander>
</DockPanel>
</GroupBox>
<GroupBox DockPanel.Dock="Bottom" Header="Other Parameters">
<DockPanel x:Name="BindPanel" VerticalAlignment="Stretch">
<ScrollViewer VerticalScrollBarVisibility="Auto" DockPanel.Dock="Top" >
<Grid x:Name="paramGrid" Margin="3" Background="Yellow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30"/>
<ColumnDefinition Width="200*"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="363*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<GridSplitter Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeDirection="Columns" Width="5" Height="Auto" ShowsPreview="false"/>
<Label Content="ID" FontWeight="Bold" HorizontalAlignment="Center"/>
<Label Content="Name" Grid.Column="1" FontWeight="Bold" HorizontalAlignment="Left"/>
<Label Content="Values" Grid.Column="3" FontWeight="Bold" HorizontalAlignment="Left"/>
<TextBlock Grid.Row="1" Text="1"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="p10"/>
<TextBlock Grid.Row="1" Grid.Column="4" Text="bla"/>
<TextBlock Grid.Row="2" Text="2"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="p11"/>
<TextBlock Grid.Row="2" Grid.Column="4" Text="blub"/>
</Grid>
</ScrollViewer>
<Grid DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Background="AliceBlue" MinHeight="30">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="123"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Content="_Load Settings" HorizontalAlignment="Left"/>
<Button Content="_Save Settings" Grid.Column="1" HorizontalAlignment="Left"/>
<Button Content="_Run Simulation" Grid.Column="2" HorizontalAlignment="Right"/>
</Grid>
</DockPanel>
</GroupBox>
</DockPanel>
Thanks in advance!
Give your ScrollViewer a MaxHeight to get the scroll working instead of overlapping
Well, I solved the problem by changing the DockPanel (named BindPanel) by a Grid with two rows (the 2nd row has a fixed height) and it works. Here the interesting part:
<GroupBox DockPanel.Dock="Bottom" Header="Other Parameters">
<Grid x:Name="BindPanel" VerticalAlignment="Stretch" Background="Beige">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="24"/>
</Grid.RowDefinitions>
<ScrollViewer VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
...
</ScrollViewer>
<!-- grid wih buttons -->
</Grid>
</GroupBox>

Cannot get TextBlock to word wrap inside a ListBox

I am having trouble getting the text in a TextBlock to wrap. The TextBlock is inside a Grid, which is part of a ListBoxItem template. Below is my XAML:
<ListBox Grid.Row="2" ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalAlignment="Center" VerticalAlignment="Top" Height="600" Width="600" Name="lb_TestResults" ItemsSource="{Binding Test}" Margin="5,5,5,5">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="DarkGray" BorderThickness="1" Padding="4">
<Grid Width="auto">
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition Height="auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBlock Name="tb_nameLabel" Margin ="0, 0, 3, 0" FontSize="15" FontFamily="Verdana" Grid.Row="0" Grid.Column="0"><Bold>Test: </Bold></TextBlock>
<TextBlock Name="tb_Name" Text="{Binding Name}" FontSize="15" FontFamily="Verdana" Grid.Row="0" Grid.Column="1"></TextBlock>
<TextBlock Name="tb_descLabel" Margin="0, 0, 3, 0" TextWrapping="Wrap" Grid.Row="1" Grid.Column="0"><Bold>Description: </Bold></TextBlock>
<TextBlock Name="tb_Description" Text="{Binding Description}" Grid.Row="1" Grid.Column="1" ></TextBlock>
<TextBlock Name="tb_statusLabel" Margin="0, 0, 3, 0" Grid.Row="2" Grid.Column="0"><Bold>Status: </Bold></TextBlock>
<TextBlock Name="tb_Status" Text="{Binding Status}" Grid.Row="2" Grid.Column="1"></TextBlock>
<TextBlock Name="tb_resultLabel" Margin="0, 0, 3, 0" Grid.Row="3" Grid.Column="0"><Bold>Result: </Bold></TextBlock>
<TextBlock Name="tb_Result" Text="{Binding Result}" Grid.Row="3" Grid.Column="1"></TextBlock>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I originally had the TextBlocks inside StackPanels, but reading various other questions on this topic such as this, I decided to change it to a Grid. I only need the TextBlock tb_Description to word wrap. Right now the output looks like this:
As you can see the text is not wrapping.
I have tried setting the width explicitly on the TextBlocks, the Grid columns, and the ListBox, but nothing has helped so far. I also disabled the horizontal scrollbar, the scrollbar is gone now but the text is still trailing off the edge. Any ideas?
The problem is not with the ListBox but with the Grid you are using to align text blocks. Both columns are set to Auto which results in Grid allowing columns to occupy all space their content requests for.
You need to set Width of the second ColumnDefinition to *:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
Hi you must set the 2nd column to * so it stretches and you have swapped the TextBlock that should wrap, just a "typo" :)
Change
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<!-- And these here you have set the wrong textblock to wrap =) -->
<TextBlock Name="tb_descLabel" Margin="0, 0, 3, 0" TextWrapping="Wrap" Grid.Row="1" Grid.Column="0"><Bold>Description: </Bold></TextBlock>
<TextBlock Name="tb_Description" Text="{Binding Description}" Grid.Row="1" Grid.Column="1" ></TextBlock>
To
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ..... -->
<TextBlock Name="tb_descLabel" Margin="0, 0, 3, 0" Grid.Row="1" Grid.Column="0"><Bold>Description: </Bold></TextBlock>
<TextBlock Name="tb_Description" Text="{Binding Description}" Grid.Row="1" Grid.Column="1" TextWrapping="Wrap"></TextBlock>
Result
Cheers!

Categories