I am trying to display something like a score board, with team name in top 25% of a square and score taking up lower 75% (with font ratios as appropriate). I also want these controls to grow/shrink as the window gets resized.
To do this I have created a grid and split it into *
and 3*
rows. I have added one TextBlock to the top row and another TextBlock spanning bottom 4 rows. Then I have wrapped each TextBox in a ViewBox
This causes an application to go into a "break mode".
This shows the issue:
<Window x:Class="WpfRandoms.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfRandoms"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<ListView ItemsSource="{Binding Teams}" HorizontalAlignment="Center" Grid.Row="0" BorderBrush="{x:Null}" Background="{x:Null}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border Margin="10" Padding="10" CornerRadius="5" Width="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<Viewbox Grid.Row="0">
<TextBlock Text="{Binding Name}" TextAlignment="Center" />
</Viewbox>
<Viewbox Grid.Row="1">
<TextBlock Text="{Binding Score}" FontSize="40" TextAlignment="Center" />
</Viewbox>
</Grid>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Window>
With code-behind:
using System.Collections.Generic;
using System.Windows;
namespace WpfRandoms
{
public partial class MainWindow : Window
{
public class Team
{
public string Name { get; set; }
public int Score { get; set; }
}
public IList<Team> Teams { get; private set; }
public MainWindow()
{
InitializeComponent();
Teams = new List<Team>();
Teams.Add(new Team() { Name = "Team A", Score = 78 });
Teams.Add(new Team() { Name = "Team B", Score = 1 });
Teams.Add(new Team() { Name = "Team C", Score = 101 });
DataContext = this;
}
}
}
This seems to be caused by the StackPanel used as ItemsPanelTemplate of a ListView (without this StackPanel everything works fine but the layout is not as desired). However, I am not aware of another way of making ListView horizontal, so I am stuck with the StackPanel.
After some experimenting and reading about how ViewBox works, and how StackPanels behave I arrived at some solution (possibly not the best one).
I am wrapping my ListView in a Border, and then binding the height of a Border within the ListView's DataTemplate to the height of that outside Border.
Because of that there is a small limitation - mainly top/bottom margins cause the elements of the ListView to be trimmed. To avoid this trimming I have added padding to the Border within the DataTemplate, and then added a smaller Border within that has a background etc.
I had to also hide the vertical scrollbar of the ListView.
Here is what I have:
<Window x:Class="WpfRandoms.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<Border x:Name="MyBorder" Margin="10" Grid.Row="0">
<ListView ItemsSource="{Binding Teams}" HorizontalAlignment="Center" VerticalAlignment="Stretch" BorderBrush="{x:Null}" Background="{x:Null}" ScrollViewer.VerticalScrollBarVisibility="Hidden">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Border Margin="10, 0" Padding="10" Height="{Binding ActualHeight, ElementName=MyBorder}" Width="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}">
<Border Background="AliceBlue" CornerRadius="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
</Grid.RowDefinitions>
<Viewbox Grid.Row="0">
<TextBlock Text="{Binding Name}" TextAlignment="Center"/>
</Viewbox>
<Viewbox Grid.Row="1">
<TextBlock Text="{Binding Score}" FontSize="40" TextAlignment="Center"/>
</Viewbox>
</Grid>
</Border>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Border>
</Grid>
</Window>
If there is a better solution, I would greatly appreciate it :)