Align TextBlocks in a ListViewItem - wpf

I have a ListView with few TextBlocks in it. I would like to align those textblocks to get columns, but the problem is that content can have different length.
Is there any way to set the length of each text block, and if the value is shorter, to add spaces?
<ListView x:Name="InfoBird_ListView" IsItemClickEnabled="False" IsHitTestVisible="False">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:SelectedBirdData">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding dataId}" Margin = "0,0,0,0" FontSize="16" />
<TextBlock Text=":" Margin = "0" FontSize="16" />
<TextBlock Text="{Binding latitude}" Margin = "10,0,0,0" FontSize="16" />
<TextBlock Text="{Binding longitude}" Margin = "10,0,0,0" FontSize="16" />
<TextBlock Text="{Binding altitude}" Margin = "10,0,0,0" FontSize="16" />
<TextBlock Text="{Binding timeStamp}" Margin = "10,0,0,0" FontSize="16" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>

There are two ways to go about this,
Set a constant Width for all the Textbox's such that they all fit the data.
Use a Grid and Grid.ColumnDefinitions to create a tabular structure such that you can fit the data into columns. Below is the updated `DataTemplate:
<Grid Margin="5,40">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="21*"/>
<ColumnDefinition Width="7*"/>
<ColumnDefinition Width="76*"/>
<ColumnDefinition Width="87*"/>
<ColumnDefinition Width="75*"/>
<ColumnDefinition Width="1224*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding dataId}" Margin = "0,0,0,0" FontSize="16" Grid.Column="0"/>
<TextBlock Text=":" Margin = "0" FontSize="16" Grid.Column="1"/>
<TextBlock Text="{Binding latitude}" Margin = "10,0,0,0" FontSize="16" Grid.Column="2"/>
<TextBlock Text="{Binding longitude}" Margin = "10,0,0,0" FontSize="16" Grid.Column="3"/>
<TextBlock Text="{Binding altitude}" Margin="10,0,0,0" FontSize="16" Grid.Column="4"/>
<TextBlock Text="{Binding timeStamp}" Margin = "10,0,0,0" FontSize="16" Grid.Column="5"/>
</Grid>
The 2nd approach is more adaptive to dynamic Window Sizes

Related

Binding Listbox in windows phone

I have 2 textblocks in a listbox datatemplate.
I want to display list of names in alphabetical order. The first textblock should show the first character of names only at the start of the string with that character and the second textblock should show the string.
Please check the below link
http://i.stack.imgur.com/4mdtu.png
It is like:
A Ana
Andrew
Andy
B Bane
Bob
C Chris
Christian
Catherine
I tried this:
XAML:
<ListBox Height="331" Name="lstBoxPlayers" MinHeight="200" MinWidth="150" Margin="0,0,0,20" SelectionChanged="lstBoxPlayers_SelectionChanged"
Tap="lstBoxPlayers_Tap" >
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="0,0,0,1" MinWidth="200" Margin="0,0,0,0" Grid.Column="0">
<Grid Background="White" MinWidth="200" Height="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Abrev" Text="{Binding Path=PlayerShortName[0]}" FontSize="30" Foreground="Black" Height="Auto" Width="26" TextAlignment="Center">
</TextBlock>
<TextBlock Grid.Column="1" Text="{Binding PlayerShortName}" Foreground="Black" FontSize="16" Height="29" MaxWidth="160" Margin="-25,0,0,0" TextAlignment="Center">
</TextBlock>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
code behind:
lstBoxPlayers.ItemsSource = PlayerList; //List of string
You can use GroupBy to form Alphabetic groups and then bind the resultant Collection of groups to the ListBox..
The code behind would look like:
lstBoxPlayers.ItemsSource = PlayerList.GroupBy( p => p.PlayerShortName[ 0 ] );
And the Xaml in you Grid would look like:
<!--Key of the Group-->
<TextBlock x:Name="Abrev" Text="{Binding Path=Key}" FontSize="30" Foreground="Black" Height="Auto" Width="26" TextAlignment="Center" VerticalAlignment="Top"></TextBlock>
<!--Values of the Group-->
<ItemsControl Grid.Column="1" ItemsSource="{Binding}" Margin="-25,0,0,0" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Grid.Column="1" Text="{Binding PlayerShortName}" Foreground="Black" FontSize="16" Height="29" MaxWidth="160" TextAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Placing a textblock in a certain grid column

I populate a textblock with data from Service and I bind the data to Listbox and then display it in textblocks, so far so good. My problem is that I want each textblock content to be placed in certain space in certain column, but this doesn't seem to work as my text is just put in each line and is not alligned as it should be.
here is my code:
<Grid x:Name="BranchesGrid" Margin="12,0,-12,6" Grid.Row="2" Height="542" VerticalAlignment="Bottom">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<ListBox Height="530" HorizontalAlignment="Left" Margin="12,6,0,0" Name="listBox1" VerticalAlignment="Top" Width="456" Grid.ColumnSpan="4">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ID}" FontSize="20" Grid.Column="0" Padding="55,10,5,10" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Name}" FontSize="20" Grid.Column="1" Padding="110,10,5,10" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding City}" FontSize="20" Grid.Column="2" Padding="70,10,5,10" HorizontalAlignment="Center"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Where seems to be the problem?
Try this:
<Grid x:Name="BranchesGrid" Margin="12,0,-12,6" Grid.Row="2" Height="542" VerticalAlignment="Bottom">
<ListBox Height="530" HorizontalAlignment="Left" Margin="12,6,0,0" Name="listBox1" VerticalAlignment="Top" Width="456" Grid.ColumnSpan="4">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding ID}" FontSize="20" Grid.Column="0" Padding="55,10,5,10" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding Name}" FontSize="20" Grid.Column="1" Padding="110,10,5,10" HorizontalAlignment="Center"/>
<TextBlock Text="{Binding City}" FontSize="20" Grid.Column="2" Padding="70,10,5,10" HorizontalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

How to bind WPF TextBlock to right top corner?

Please help me to edit XAML so the TextBlock which shows minutes goes to the right top corner.
<StackPanel Orientation="Horizontal" >
<StackPanel Orientation="Horizontal" >
<TextBlock Name="UserNameTextBlock" Margin="0,0,8,0" VerticalAlignment="Bottom" FontSize="15" Text="{Binding Path=UserName}" FontWeight="Bold"></TextBlock>
<TextBlock FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Foreground="LightGray" >#</TextBlock>
<TextBlock FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Name="ScreenNameTextBlock" Text="{Binding Path=ScreenName}" Foreground="Gray" ></TextBlock>
<TextBlock FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Name="MinAgo" Text="{Binding Path=MinAgo}" Foreground="Gray" ></TextBlock>
</StackPanel>
</StackPanel>
So it should be like
I would use a DockPanel. For the child nodes, just add DockPanel.Dock attributes to indicate where you want the element to go. The last child element will automatically fill the remaining area.
<DockPanel>
<TextBlock DockPanel.Dock="Right" FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Name="MinAgo" Text="{Binding Path=MinAgo}" Foreground="Gray" ></TextBlock>
<StackPanel Orientation="Horizontal" >
<TextBlock Name="UserNameTextBlock" Margin="0,0,8,0" VerticalAlignment="Bottom" FontSize="15" Text="{Binding Path=UserName}" FontWeight="Bold"></TextBlock>
<TextBlock FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Foreground="LightGray" >#</TextBlock>
<TextBlock FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Name="ScreenNameTextBlock" Text="{Binding Path=ScreenName}" Foreground="Gray" ></TextBlock>
</StackPanel>
</DockPanel>
If I were doing this I would use a grid rather than a horizontal stack panel:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Name="UserNameTextBlock" Margin="0,0,8,0" VerticalAlignment="Bottom" FontSize="15" Text="{Binding Path=UserName}" FontWeight="Bold"></TextBlock>
<TextBlock Grid.Column="1" FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Foreground="LightGray" >#</TextBlock>
<TextBlock Grid.Column="2" FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Name="ScreenNameTextBlock" Text="{Binding Path=ScreenName}" Foreground="Gray" ></TextBlock>
<TextBlock Grid.Column="4" FontSize="13" VerticalAlignment="Bottom" Padding="0,0,0,1" Name="MinAgo" Text="{Binding Path=MinAgo}" Foreground="Gray" ></TextBlock>
</Grid>
Note the * in the column 3 which means that column will use all available space after column 2, except for what is needed by column 4.
Don't use a StackPanel but a Grid with columns?

textblock in user control TextWrapping not wrapping

I created user control with the textblock. But it will not wrap. This user control servers as a listboxitem.
<Grid x:Name="MainGrid" Height="Auto" Width="Auto">
<StackPanel Orientation="Horizontal">
<Image Height="50" Width="100" Stretch="Uniform" Name="image1" Source="{Binding Path=VideoImageUrl}" Margin="12,12,13,84" MouseLeftButtonDown="image1_MouseLeftButtonDown" MouseEnter="image1_MouseEnter" MouseLeave="image1_MouseLeave" />
<StackPanel Orientation="Vertical" >
<TextBlock TextWrapping="Wrap" Height="Auto" HorizontalAlignment="Left" Name="titleTextBox"
Text="{Binding Path=Title, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}"
VerticalAlignment="Center" Width="Auto" FontSize="14" FontWeight="SemiBold" />
<StackPanel Orientation="Vertical" x:Name="StackPanelDetails">
<TextBlock Height="Auto" HorizontalAlignment="Left" Name="desciptionTextBox"
TextWrapping="Wrap"
Text="{Binding Path=Desciption, Mode=OneWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}"
VerticalAlignment="Center" Width="Auto" />
<Line />
<ItemsControl x:Name="CustomItemsSource" ItemsSource="{Binding Path=LinksList}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock>
<Hyperlink NavigateUri="{Binding Path=TopicUrl}" RequestNavigate="Hyperlink_RequestNavigate" >
<TextBlock Text="{Binding Path=TopicName}" />
</Hyperlink>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
A ListBox's default template does not automatically limit the width of its items, but instead uses a ScrollViewer, which shows a horizontal scrollbar when an item is wider than the ListBox.
You can remove the ScrollViewer by replacing the ListBox's Template:
<ListBox ...>
<ListBox.Template>
<ControlTemplate>
<StackPanel IsItemsHost="True"/>
</ControlTemplate>
</ListBox.Template>
...
</ListBox>
Another important thing to note is that a StackPanel in the top-level Grid won't properly resize the contained elements. In the following simplified example the text in the TextBlock is not wrapped because the containing StackPanel simply does not resize it as you expect:
<Grid>
<StackPanel Orientation="Horizontal">
<Image ... />
<Text TextWrapping="Wrap" Text=... />
</StackPanel>
</Grid>
This way it works as you expect:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image ... />
<TextBlock Grid.Column="1" TextWrapping="Wrap" Text=... />
</Grid>

WPF ListView with column names?

I have this ListView and I'm using a DataTemplate (as you can see) for items.
How can i add column names to the ListView with this ItemTemplate definition?
I cannot use that GridViewColumn definition, because this ListView uses lazy data loading, so when there are too many rows, it fetches them on demand. GridViewColumn somehow does not function with this lazy loading.
<ListView Grid.Row="3">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="grid" Background="Transparent" MinWidth="580" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="220" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="80"/>
</Grid.ColumnDefinitions>
<TextBlock VerticalAlignment="Center" Grid.Column="0" Text="{Binding Path=Benutzer.Value.Code}"/>
<TextBlock VerticalAlignment="Center" Grid.Column="1" Text="{Binding Path=Nachname}"/>
<TextBlock VerticalAlignment="Center" Grid.Column="2" Text="{Binding Path=Vorname}"/>
<TextBlock VerticalAlignment="Center" Grid.Column="3">
<TextBlock.Text>
<Binding Path="GeburtDate" StringFormat="{}{0:d}"/>
</TextBlock.Text>
</TextBlock>
<Button VerticalAlignment="Center" Grid.Column="4" Style="{StaticResource StyleEditButton}" Content="Öffnen..." Tag="{Binding}" Click="OpenPersonButton_Click"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListView>
I don't think there is any point in using a ListView if, as you say, you cannot use GridView (or any other view). I would exchange ListView for ItemsControl (or ListBox if you need a selectable item or any of the other things that ListBox offers).
If what you say is true, you could just use a stack panel to position a header row above your data rows:
<StackPanel>
<!-- Header -->
<StackPanel Orientation="Horizontal">
<TextBlock Width="220" TextAlignment="Center" Text="Code" />
<TextBlock Width="100" TextAlignment="Center" Text="Nachname" />
<TextBlock Width="100" TextAlignment="Center" Text="Vorname" />
<TextBlock Width="70" TextAlignment="Center" Text="GeburtDate" />
</StackPanel>
<!-- Data rows -->
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" MinWidth="580">
<TextBlock Width="220" TextAlignment="Center" Text="{Binding Path=Benutzer.Value.Code}" />
<TextBlock Width="100" TextAlignment="Center" Text="{Binding Path=Nachname}" />
<TextBlock Width="100" TextAlignment="Center" Text="{Binding Path=Vorname}" />
<TextBlock Width="70" TextAlignment="Center" Text="{Binding Path=GeburtDate, StringFormat={0:d}}" />
<Button VerticalAlignment="Center" Grid.Column="4" Style="{StaticResource StyleEditButton}" Content="Öffnen..." Tag="{Binding}" Click="OpenPersonButton_Click"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Hope that helps. You might also like to read about virtualizing panels. That might provide the kind of laziness you're talking about.

Resources