Gridsplitter in a Grid with an ItemsControl - c#

I'm trying to make a PropertyGrid Custom Control. The PropertyGrid will be very similar to the PropertyGrid used in Visual Studio. I've tried using the PropertyGrid of the Extended WPF Toolkit but you have to specify the category of a property with an attribute and we need to change the categories runtime. Which as far as I know is impossible with attributes.
So I'm making the PropertyGrid myself. This is my code so far:
The Generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:HomeMadePropertyGrid"
xmlns:System="clr-namespace:System;assembly=mscorlib">
<BooleanToVisibilityConverter x:Key="BoolToVisConverter"></BooleanToVisibilityConverter>
<SolidColorBrush x:Key="GlyphBrush" Color="#444" />
<ControlTemplate x:Key="toggleButtonTemplate" TargetType="ToggleButton">
<Grid Width="15" Height="13" Background="Transparent">
<Path x:Name="ExpandPath" Fill="{StaticResource GlyphBrush}" Data="M 4 0 L 8 4 L 4 8 Z" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="1,1,1,1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Data" TargetName="ExpandPath" Value="M 0 4 L 8 4 L 4 8 Z"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="toggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Template" Value="{StaticResource toggleButtonTemplate}" />
</Style>
<Style TargetType="{x:Type local:PropertyGrid}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:PropertyGrid}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsControl ItemsSource="{TemplateBinding ItemsSource}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Background="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}">
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="toggleButton" Height="20" Width="20" Style="{StaticResource toggleButtonStyle}"/>
<TextBlock Text="{Binding Name}" FontWeight="Bold"></TextBlock>
</StackPanel>
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Visibility="{Binding ElementName=toggleButton, Path=IsChecked, Converter={StaticResource BoolToVisConverter}}"
Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border BorderThickness="1" BorderBrush="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}">
<TextBlock Background="White" Text="{Binding Path=Name}"/>
</Border>
<GridSplitter Width="1"
Grid.RowSpan="4" Grid.Column="1"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}"/>
<Border Grid.Column="2" BorderThickness="1" BorderBrush="{Binding GridColor, RelativeSource={RelativeSource AncestorType=local:PropertyGrid}}">
<ContentPresenter Grid.Column="2" Content="{Binding Value}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type System:String}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Int32}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Right"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Double}">
<TextBox Text="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
TextAlignment="Right"
BorderThickness="0"/>
</DataTemplate>
<DataTemplate DataType="{x:Type System:Boolean}">
<CheckBox IsChecked="{Binding Path=Content, RelativeSource={RelativeSource AncestorType={x:Type ContentPresenter}}}"
HorizontalAlignment="Center"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
PropertyGrid.cs
public class PropertyGrid : ItemsControl
{
public Brush GridColor
{
get { return (Brush)GetValue(GridColorProperty); }
set { SetValue(GridColorProperty, value); }
}
public static readonly DependencyProperty GridColorProperty =
DependencyProperty.Register("GridColor", typeof(Brush), typeof(PropertyGrid), new UIPropertyMetadata(new SolidColorBrush(Colors.Transparent)));
static PropertyGrid()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(PropertyGrid), new FrameworkPropertyMetadata(typeof(PropertyGrid)));
}
}
PropertyGroup
public class PropertyGroup
{
public string Name { get; set; }
public List<PropertyGridItem> Items { get; set; }
public PropertyGroup()
{
Items = new List<PropertyGridItem>();
Name = "";
}
}
PropertyGridItem
public class PropertyGridItem
{
public string Name { get; set; }
public object Value { get; set; }
public PropertyGridItem(string propertyName, object propertyValue)
{
Name = propertyName;
Value = propertyValue;
}
}
This code in my MainWindow.xaml:
<local:PropertyGrid ItemsSource="{Binding Path=Groups}" GridColor="#f0f0f0"/>
Code behind of my ViewModel:
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
The ViewModel
public class ViewModel
{
public List<PropertyGroup> Groups { get; set; }
public ViewModel()
{
Groups = new List<PropertyGroup>();
PropertyGroup group1 = new PropertyGroup();
group1.Name = "Group1";
group1.Items.Add(new PropertyGridItem("Item1", "test"));
group1.Items.Add(new PropertyGridItem("Item2", 300));
group1.Items.Add(new PropertyGridItem("Item3", true));
group1.Items.Add(new PropertyGridItem("Item4", 5.2));
Groups.Add(group1);
PropertyGroup group2 = new PropertyGroup();
group2.Name = "Group2";
group2.Items.Add(new PropertyGridItem("Item1", "test"));
group2.Items.Add(new PropertyGridItem("Item2", 300));
group2.Items.Add(new PropertyGridItem("Item3", true));
group2.Items.Add(new PropertyGridItem("Item4", 5.2));
Groups.Add(group2);
}
}
The problem I'm having is that the GridSplitter is applied every row. I want the GridSplitter to be applied to all rows of a group. I understand that this is because I make a new Grid for every item. For the attached properties to work the items have to be a direct child of the Grid.
A DataGrid also isn't an option because the GridSplitter is only available between column headers.
So to make a long story short: how can I use a Grid in an ItemsControl with a GridSplitter that applies to all rows of ideally a group or the entire Grid if that isn't possible.

I finally found the solution to this problem.
To get this to work I had to:
Set the Grid.IsSharedSizeScope to true on the parent ItemsControl.
Set the SharedSizeGroup property on the name column with an arbitrary name.
Remove the star sizing on the name column. Having both the first and third column with star sizing resulted in a stuck GridSplitter for some reason.
Set a fixed width on the GridSplitter, I set the Width to 2.
Set the ResizeBehaviour of the GridSplitter to PreviousAndNext.
Here is a relevant piece of the resulting code:
<ItemsControl ItemsSource="{Binding Items}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Visibility="{Binding ElementName=toggleButton, Path=IsChecked, Converter={StaticResource BoolToVisConverter}}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="nameColumn"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Style="{StaticResource BodyPropertyGrid_CellBorder}">
<TextBlock Text="{Binding Path=Name}"/>
</Border>
<GridSplitter Grid.Column="1" Width="2"
ResizeBehavior="PreviousAndNext"
Style="{StaticResource BodyPropertyGridSplitter}"/>
<Border Grid.Column="2" Style="{StaticResource BodyPropertyGrid_CellBorder}">
<ContentControl Content="{Binding}"
ContentTemplateSelector="{StaticResource propertyItemTemplateSelector}"/>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Unfortunately you didn't provide us with a nice simple piece of code that only demonstrates your problem and I don't have time to get it to compile and run in my test project, so I can only give you suggestions and not tested solutions. Next time, please take the time to show a code example that we can just copy and paste into a project.
You might be able to get your 'stretched' GridSplitter if you join all of the row Grids using the Grid.IsSharedSizeScope Attached Property:
<Grid Visibility="{Binding ElementName=toggleButton, Path=IsChecked, Converter=
{StaticResource BoolToVisConverter}}" Grid.IsSharedSizeScope="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" SharedSizeGroup="FirstColumn" />
<ColumnDefinition Width="Auto" SharedSizeGroup="GridSplitterColumn" />
<ColumnDefinition Width="*" SharedSizeGroup="LastColumn" />
</Grid.ColumnDefinitions>
...
</Grid>

Related

Binding in doesn't seem to work inside a custom DataTemplate (Expander)

Overview
I'm trying to create a custom expander which contains a visual tree where the user can select or deselect nodes. But the tree is not important for now. Important is the header which I had to overwrite so I can show all the information the user needs.
Issue
Somehow the Binding of the textboxes inside the DataTemplate doesn't work at all. No matter what I enter into the fields are always empty and the setter of the DependencyProperty doesn't get called.
Code
<UserControl x:Class="WPF_Test_project.CheckableTree"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid>
<Grid.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="ExpanderToggleButton" TargetType="ToggleButton">
<Path Name="Chevron"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 10 10 L 20 0 Z"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Foreground}"
/>
<!-- Change appearance when is expanded -->
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter TargetName="Chevron" Property="Data" Value="M 0 10 L 10 0 L 20 10 Z" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="MainViewExpander" TargetType="Expander">
<Setter Property="Foreground" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Expander">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Name="ContentRow" Height="0" />
</Grid.RowDefinitions>
<Border Name="HeaderBorder"
Grid.Row="0"
BorderThickness="0"
Background="#FFE1E1E1"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<ContentPresenter
Grid.Column="0"
Margin="0"
ContentSource="Header"
RecognizesAccessKey="True"
/>
<ToggleButton
Grid.Column="2"
Margin="4 4 8 4"
IsChecked="{Binding Path=IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
OverridesDefaultStyle="True"
Template="{StaticResource ExpanderToggleButton}"
Background="Black"
/>
</Grid>
</Border>
<Border Name="ContentBorder" Grid.Row="1" BorderThickness="0">
<ContentPresenter Margin="0" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ContentRow" Property="Height" Value="{Binding ElementName=Content, Path=DesiredHeight}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
Margin="4"
/>
<TextBlock Grid.Column="1"
Margin="2"
Text="{Binding ElementName=CT, Path=Header, FallbackValue=Header}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
/>
<TextBlock Grid.Column="2"
Margin="2"
Text="{Binding ElementName=CT, Path=NrOfFeaturesSelected, FallbackValue=5}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
HorizontalAlignment="Right"
/>
<TextBlock Grid.Column="3"
Margin="2"
Text="/"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
HorizontalAlignment="Right"
/>
<TextBlock Grid.Column="4"
Margin="2"
Text="{Binding ElementName=CT, Path=NrOfFeaturesAvailable, FallbackValue=5}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
HorizontalAlignment="Right"
/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TreeViewItemStyle" TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<Expander IsExpanded="True" Style="{StaticResource MainViewExpander}">
<TreeView ItemsSource="{Binding ElementName=CT, Path=Items}"
BorderThickness="0"
ItemContainerStyle="{StaticResource TreeViewItemStyle}"
Padding="4"
>
<TreeView.Resources>
<HierarchicalDataTemplate
x:Key="CheckableTreeItemTemplate"
ItemsSource="{Binding ElementName=CT, Path=Items}"
>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
IsChecked="{Binding IsChecked}"
VerticalAlignment="Center"
Visibility="{Binding IsCheckable, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
<Label Grid.Column="1"
Content="{Binding Title}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
/>
<Label Grid.Column="3"
Content="{Binding TagCountDisplayValue}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Visibility="{Binding ShowTagCountDisplayValue, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</Grid>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Expander>
</Grid>
</UserControl>
Class
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
namespace WPF_Test_project
{
/// <summary>
/// Interaction logic for CheckableTree.xaml
/// </summary>
public partial class CheckableTree : UserControl
{
public CheckableTree()
{
InitializeComponent();
}
public int NrOfFeaturesSelected
{
get { return (int)GetValue(NrOfFeaturesSelectedProperty); }
set { SetValue(NrOfFeaturesSelectedProperty, value); }
}
public static readonly DependencyProperty NrOfFeaturesSelectedProperty =
DependencyProperty.Register("NrOfFeaturesSelected", typeof(Int32), typeof(CheckableTree), new UIPropertyMetadata(null));
public int NrOfFeaturesAvailable
{
get { return (int)GetValue(NrOfFeaturesSelectedProperty); }
set { SetValue(NrOfFeaturesSelectedProperty, value); }
}
public static readonly DependencyProperty NrOfFeaturesAvailableProperty =
DependencyProperty.Register("NrOfFeaturesAvailable", typeof(Int32), typeof(CheckableTree), new UIPropertyMetadata(null));
public IEnumerable<object> Items
{
get { return (IEnumerable<object>)GetValue(ItemsProperty); }
set { SetValue(NrOfFeaturesSelectedProperty, value); }
}
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.Register("Items", typeof(IEnumerable<object>), typeof(CheckableTree), new UIPropertyMetadata(null));
public string Header
{
get { return (string)GetValue(HeaderProperty); }
set { SetValue(HeaderProperty, value); }
}
public static readonly DependencyProperty HeaderProperty =
DependencyProperty.Register("Header", typeof(string), typeof(CheckableTree), new UIPropertyMetadata(null));
}
}
Usage
<local:CheckableTree Header="Test" NrOfFeaturesSelected="9">
</local:CheckableTree>
But I always get the Fallback Values. Does anybody know why this happens? Do I have to link the DataTemplate to the Control Class or something?
Solution (Thanks to mm8)
For every binding in the DataTemplate refer to the parent UserControl
<Textbox
...
Text={Binding Path=XY, RelativeSource={RelativeSource AncestorType=UserControl}, FallbackValue=...}"
... />
Try to bind to the Header property of the parent UserControl using a {RelativeSource}:
<TextBlock Grid.Column="1"
Margin="2"
Text="{Binding Path=Header, RelativeSource={RelativeSource AncestorType=UserControl}, FallbackValue=Header}"
Foreground="Black"
FontWeight="Bold"
FontSize="14"
/>

WPF - Ticking checkbox when clicking anywhere on a datagrid row

The picture shows an example of some items added in my datagrid. Right now I can only change each rows checkbox by clicking on it but I would like to be able to click anywhere on each row to change that rows checkbox.
XAML of datagrid and row template:
<DataGrid Grid.Row="1" SnapsToDevicePixels="True" BorderThickness="0" SelectedItem="{Binding Selected}" ItemsSource="{Binding Source={StaticResource ColViewSource},Mode=OneWay}" AutoGenerateColumns="False" x:Name="dataGrid" HeadersVisibility="None" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<DataGrid.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupHeaderStyle}">
<GroupStyle.Panel>
<ItemsPanelTemplate>
<DataGridRowsPresenter></DataGridRowsPresenter>
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
<Style TargetType="DataGridRow">
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="TTC">
<Setter Property="Template" Value="{StaticResource ResourceKey=TTC}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="TTC">
<Grid Style="{StaticResource rowGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30"/>
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Style="{StaticResource commentboxStyle}" Text="{Binding Comment,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" Grid.ColumnSpan="3" ></TextBox>
<TextBlock Style="{StaticResource textblockStyle}" Text="{Binding Text1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.ColumnSpan="2"/>
<Label Style="{StaticResource labelStyle}" Content="{Binding Text2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="2" HorizontalAlignment="Right" />
<CheckBox Style="{StaticResource RectBox}" IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="3" HorizontalAlignment="Center" IsThreeState="True"/>
<Path Style="{StaticResource dottedpathStyle}"/>
</Grid>
</ControlTemplate>
Any tips on how to achieve this?
You could add a handler to your DataGridRow style that sets the IsChecked property of the data object to true:
<Style TargetType="DataGridRow">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnPreviewMouseLeftButtonDown" />
<Style.Triggers>
<DataTrigger Binding="{Binding Type}" Value="TTC">
<Setter Property="Template" Value="{StaticResource ResourceKey=TTC}"/>
</DataTrigger>
</Style.Triggers>
</Style>
private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!(e.Source is CheckBox))
{
DataGridRow row = sender as DataGridRow;
YourDataClass dataObject = row.DataContext as YourDataClass;
if (dataObject != null)
dataObject.IsChecked = true;
}
}
Make sure that YourDataClass implements the INotifyPropertyChanged interface and raises the PropertyChanged event in the setter of the IsChecked property.
Prevent Code behind and use a System.Windows.Interactivity.Behaviour.
public class SelectedCheckBoxBehaviour : System.Windows.Interactivity.Behavior<FrameworkElement>
{
protected override void OnAttached()
{
AssociatedObject.MouseDown += AssociatedObject_MouseDown;
base.OnAttached();
}
private void AssociatedObject_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
FrameworkElement self = sender as FrameworkElement;
if(self != null)
{
MyViewModel dataContext = self.DataContext as MyViewModel;
dataContext.IsChecked = !dataContext.IsChecked;
}
}
protected override void OnDetaching()
{
AssociatedObject.MouseDown -= AssociatedObject_MouseDown;
base.OnDetaching();
}
}
Namespaces
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviour="clr-namespace:WpfApplication.Behaviour"
<!-- ... --->
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="30"/>
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Text="{Binding Comment,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="0" Grid.ColumnSpan="3" ></TextBox>
<TextBlock Text="{Binding Text1,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.ColumnSpan="2"/>
<Label Content="{Binding Text2,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="2" HorizontalAlignment="Right" />
<CheckBox IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Column="3" HorizontalAlignment="Center" IsThreeState="True"/>
<Path />
<i:Interaction.Behaviors>
<behaviour:SelectedCheckBoxBehaviour />
</i:Interaction.Behaviors>
</Grid>
This should work - Tut

Problems getting spreadsheet grid look with Viewbox and ListView in UWP Project

I'm trying to create a 'spreadsheet like' grid with column headers showing information from a set of player objects with the cell contents maximised in size. To do this I have a UWP app with a ListView bound to the collection of Player objects. The ListView.ItemsPanel uses a UniformGridPanel obtained from here
The UniformGridPanel has a Rows property bound to the player count which can vary, and one Column. The UniformGridPanel is used to show ALL players, giving each player item equal height, so no player is partially displayed and there is no scrolling. The UniformGridPanel is working fine.
The ListView.ItemTemplate is a Gridof a fixed number of columns representing data about each player.
My problems are:
The info in each 'Cell' is not big enough. I would like each 'cell' content maximised, and the grid layout to remain spreadsheet like, i.e. square, with rows and columns aligned.
I don't know how to put Headings on each of the Columns that would align with the cells in each column.
So the display looks like this below. This is the closest to what I want, but for the size of the cell contents and the column headers.
As you can see there is plenty of room to make the numbers and letters bigger. I've tried many variations using Viewbox in the XAML. For example, wrapping the ListView in a Viewbox produces this which is no good as the columns are misaligned.
If I put Viewbox around each Bordercontrol that defines a 'cell' I still get problems with the layout too.
I've tagged this post with WPF despite my problem being in a UWP context in case someone has had a similar experience in that domain that could be applied here.
CODE BEHIND:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
ObservableCollection<Player> players = new ObservableCollection<Player>();
players.Add(new Player("John", "Smith",1,99,11,1));
players.Add(new Player("Fred", "Blogs", 19, 25, 11, 1));
players.Add(new Player("Andrew", "Sykes", 19, 25, 11, 2));
players.Add(new Player("Dean", "Andrews", 19, 179, 11, 1));
this.DataContext = players;
}
}
XAML:
<Grid x:Name="root" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="grdPlayers" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<!--<Viewbox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" StretchDirection="Both" Stretch="Fill">-->
<ListView x:Name="lvwPlayers"
Padding="0"
BorderBrush="Red"
BorderThickness="5"
ItemsSource="{Binding}"
SelectionMode="None"
ScrollViewer.VerticalScrollMode="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollMode="Disabled"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<local:UniformGrid x:Name="pnlPlayer" Rows="{Binding Count}" Columns="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="grdPlayerRow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="Black" BorderThickness="1" Background="Green" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding Initials}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Border>
<Border Grid.Column="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding HighScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Border>
<Border Grid.Column="2" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding LowScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Border>
<Border Grid.Column="3" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding Average}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Border>
<Border Grid.Column="4" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock Text="{Binding TonCount}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Border>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!--</Viewbox>-->
</Grid>
</Grid>
PLAYER CODE:
public class Player : INotifyPropertyChanged
{
public Player(string firstName, string lastName, int low, int high, int avg, int tonCount)
{
FirstName = firstName;
LastName = lastName;
LowScore = low;
HighScore = high;
Average = avg;
TonCount = tonCount;
}
protected void OnPropertyChanged([CallerMemberName] string caller = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(caller));
}
public event PropertyChangedEventHandler PropertyChanged;
private int _tonCount;
public int TonCount
{
get { return _tonCount; }
set
{
_tonCount = value;
OnPropertyChanged();
}
}
private double _average;
public double Average
{
get { return _average; }
set
{
_average = value;
OnPropertyChanged();
}
}
private int _lowScore;
public int LowScore
{
get { return _lowScore; }
set
{
_lowScore = value;
OnPropertyChanged();
}
}
private int _highScore;
public int HighScore
{
get { return _highScore; }
set
{
_highScore = value;
OnPropertyChanged();
}
}
public string FullName
{
get { return $"{FirstName} {LastName}"; }
}
private string _firstName = string.Empty;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged();
OnPropertyChanged("Initials");
}
}
private string _lastName = string.Empty;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
OnPropertyChanged();
OnPropertyChanged("Initials");
}
}
public string Initials
{
get
{
return FirstName.Substring(0, 1) + LastName.Substring(0, 1).ToUpper();
}
}
public override string ToString()
{
return FullName;
}
}
UPDATE:
#Grace Feng, your answer to use the lvwPlayers loaded event before assignment of the DataContext gives the following output which is NOT what I wanted. To begin with the rows are of different heights for no reason??:
Base on your description, I think there is no need to use the UniformGridPanel, you can simply customize a Grid to make its Height equals its Width. For example, create a TemplatedControl like this:
public sealed class SquareGrid : Grid
{
public SquareGrid()
{
this.Loaded += SquareGrid_Loaded;
}
private void SquareGrid_Loaded(object sender, RoutedEventArgs e)
{
this.Height = this.ActualWidth;
}
}
And for the question of "I don't know how to put Headings on each of the Columns that would align with the cells in each column.", I think you can set them as the Header of ListView. But it's very wise of you to use ViewBox to make the Text fill the size. Here comes the demo:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="900">
<ListView x:Name="lvwPlayers"
Padding="0"
BorderBrush="Red"
BorderThickness="5"
ItemsSource="{Binding}"
SelectionMode="None"
ScrollViewer.VerticalScrollMode="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollMode="Disabled"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<!--<ListView.ItemsPanel>
<ItemsPanelTemplate>
<local:UniformGrid x:Name="pnlPlayer" Rows="{Binding Count}" Columns="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>-->
<ListView.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:SquareGrid BorderBrush="Black" BorderThickness="1">
<Viewbox>
<TextBlock Text="Initials" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="1">
<Viewbox>
<TextBlock Text="HighScore" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="2">
<Viewbox>
<TextBlock Text="LowScore" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="3">
<Viewbox>
<TextBlock Text="Average" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid BorderBrush="Black" BorderThickness="1" Grid.Column="4">
<Viewbox>
<TextBlock Text="TonCount" />
</Viewbox>
</local:SquareGrid>
</Grid>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<Grid x:Name="grdPlayerRow">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<local:SquareGrid Grid.Column="0" BorderBrush="Black" BorderThickness="1" Background="Green" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding Initials}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid Grid.Column="1" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding HighScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid Grid.Column="2" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding LowScore}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid Grid.Column="3" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding Average}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Viewbox>
</local:SquareGrid>
<local:SquareGrid Grid.Column="4" BorderBrush="Black" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Viewbox>
<TextBlock Text="{Binding TonCount}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Viewbox>
</local:SquareGrid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Rendering Image:

Table In XAml Windows Store App

My TABLE code
ItemS Control Working Perfectly But I need only one listview inside listview help i get problem in
c Get Set Class I need a Single List
Hi I Need To Generate A Table In My Metro APP BUT I GET WRONG OUTPUT PLEASE HELP I BIND HEADER AND CONTENTS SEPERATELY USING LIST
C# CODE
foreach (var item in itemsreceiveds)
{
variable2.Add(new contentdata() { firstdata = item.getFirstData, seconddata = item.getSecondData, thirddata = item.getThirdData, headers = item.getFieldName });
}
var groupedPersons = variable2.Select((emp) => new { sectionName = emp.headers }).ToList().Distinct();
foreach (var s in groupedPersons)
{
firstheader = s.sectionName;
string[] sepword = firstheader.Split('#');
firstheader = sepword[0].ToUpper();
secondheader = sepword[1].ToUpper();
thirdheader = sepword[2].ToUpper();
variableheader.Add(new contentdataheader(firstheader,secondheader,thirdheader));
groupListView.ItemsSource = variableheader;
}
//SUBITEM
foreach (var person in variable2)
{
subdata.Add(new subitems(person.firstdata, person.seconddata, person.thirddata));
}
itemListViewss.ItemsSource = subdata;
XAML
<ListView Name="groupListView" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsSwipeEnabled="True" SelectionMode="None" Grid.ColumnSpan="3" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Border x:Name="bordermenu" BorderBrush="Black" BorderThickness="1" Grid.Column="1" Grid.Row="0" Width="150">
<TextBlock Foreground="Red" Text="{Binding Firstheader}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border x:Name="bordermenu2" BorderBrush="Black" BorderThickness="1" Grid.Column="2" Grid.Row="0" Width="150">
<TextBlock Foreground="Red" Text="{Binding Secondheader}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<Border x:Name="bordermenu3" BorderBrush="Black" BorderThickness="1" Grid.Column="3" Grid.Row="0" Width="150">
<TextBlock Foreground="Red" Text="{Binding Thirdheader}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView Name="itemListViewss" CanDragItems="True" CanReorderItems="True" AllowDrop="True" IsSwipeEnabled="True" SelectionMode="None" Grid.ColumnSpan="3" Grid.Row="1">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" >
<Border x:Name="bordersubmenu" BorderBrush="Black" BorderThickness="1" Grid.Column="1" Grid.Row="1" Width="150">
<TextBlock Foreground="Blue" Text="{Binding dynamic}" x:Name="submenu" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Border x:Name="bordersubmenu2" BorderBrush="Black" BorderThickness="1" Grid.Column="2" Grid.Row="1" Width="150">
<TextBlock Foreground="Blue" Text="{Binding p1}" x:Name="submenu2" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<Border x:Name="bordersubmenu3" BorderBrush="Black" BorderThickness="1" Grid.Column="3" Grid.Row="1" Width="150">
<TextBlock Foreground="Blue" Text="{Binding p2}" x:Name="submenu3" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I Get Ouput As
But I Need Output As This
Here's the simplest answer - a working demo.
I didn't do everything for you, mate, but I sure did a lot. You'll have to code a little to get it just how you like. If you are using a custom control suite, most of this might be done for you. If not, this will get you down the road. Far down the road.
Take this code behind:
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
}
public class Datum
{
public DateTime Date { get; set; }
public string Year { get { return Date.ToString("yyy"); } }
public string Month { get { return Date.ToString("MMMM"); } }
public string Day { get { return Date.ToString("dd"); } }
public string Weekday { get { return Date.ToString("dddd"); } }
}
public class ViewModel
{
public ViewModel()
{
// data
var _Data = Enumerable.Range(1, 20)
.Select(x => new Datum { Date = DateTime.Now.Add(TimeSpan.FromDays(x * 14)) });
Data = new ObservableCollection<Datum>(_Data);
}
public ObservableCollection<Datum> Data { get; private set; }
}
And then try this XAML:
<Page.DataContext>
<local:ViewModel/>
</Page.DataContext>
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<StackPanel>
<Grid Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="White" />
<Setter Property="Padding" Value="5" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
</Style>
</Grid.Resources>
<Border Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="4">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
<TextBlock VerticalAlignment="Center" TextAlignment="Right">
<Run Text="Search" />
<LineBreak />
<Run Text="Data" />
</TextBlock>
<TextBox Width="100" />
</StackPanel>
</Border>
<Border Grid.Column="0" Grid.Row="1"><TextBlock Text="Year" /></Border>
<Border Grid.Column="1" Grid.Row="1"><TextBlock Text="Month" /></Border>
<Border Grid.Column="2" Grid.Row="1"><TextBlock Text="Day" /></Border>
<Border Grid.Column="3" Grid.Row="1"><TextBlock Text="Weekday" /></Border>
</Grid>
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Width="400">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="5,0" />
</Style>
</Grid.Resources>
<TextBlock Grid.Column="0" Text="{Binding Year}" />
<TextBlock Grid.Column="1" Text="{Binding Month}" />
<TextBlock Grid.Column="2" Text="{Binding Day}" />
<TextBlock Grid.Column="3" Text="{Binding Weekday}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Grid Width="400">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.Resources>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="White" />
<Setter Property="Padding" Value="5" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Black" />
</Style>
</Grid.Resources>
<Border Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="4">
<TextBlock Text="Showing 1 to 10 of 371" HorizontalAlignment="Right" />
</Border>
</Grid>
</StackPanel>
</Grid>
You should get something like this:
To add to Jerry's XAML in his answer. You can replace the ItemsControl with a ListBox (same template/itemTemplate modifications) to get the same view, but also the ability to use SelectedIndex, but I don't know if that applies to this question.
Note: I did find you need to add a Width to the ListBox. You can't just let the Grid in the ItemTemplate do it.
Maybe you're looking for something like this.
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Fill="Black" Grid.ColumnSpan="2" Grid.Row="0" />
<TextBlock Text="Integer" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" Grid.Row="0" Grid.Column="0" FontSize="14" />
<TextBlock Text="String" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" Grid.Row="0" Grid.Column="1" FontSize="14" />
<ListView x:Name="ListViewDisplay" ItemsSource="{Binding}" Grid.Row="1" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="Black" Background="White" RequestedTheme="Light">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Integer}" Margin="5" Grid.Column="0" FontSize="14" />
<TextBlock Text="{Binding String}" Margin="5" Grid.Column="1" FontSize="14" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Behind code:
public sealed partial class SamplePage : Page
{
ObservableCollection<ROWS> r = new ObservableCollection<ROWS>();
public SamplePage()
{
this.InitializeComponent();
r.Add(new ROWS { Integer = 1, String = "ONE" });
r.Add(new ROWS { Integer = 2, String = "TWO" });
r.Add(new ROWS { Integer = 3, String = "THREE" });
r.Add(new ROWS { Integer = 4, String = "FOUR" });
r.Add(new ROWS { Integer = 5, String = "FIVE" });
ListViewDisplay.ItemsSource = r;
}
}
public class ROWS {
public int Integer { get; set; }
public string String { get; set; }
}
Result:

Binding ObservableCollection of List

In my Windows Phone application I have a listBox with ContentItems binding :
private ObservableCollection<ContentItemViewModel> _contentItems;
public ObservableCollection<ContentItemViewModel> ContentItems
{
get { return _contentItems; }
}
<ListBox x:Name="ContentListBox" Margin="0,117,12,0" VirtualizingStackPanel.VirtualizationMode="Standard" Logic1:TiltEffect.IsTiltEnabled="True" ItemsSource="{Binding ContentItems}" Tap="ContentListBox_Tap" MinHeight="656" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="vertical" >
<Grid Height="{Binding ItemHeight}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" x:Name="itemIco1" Width="Auto" Height="Auto" HorizontalAlignment="Left" Source="{Binding IconURL}" Stretch="Fill" CacheMode="BitmapCache" VerticalAlignment="Top" Margin="5,5,5,5" Visibility="Visible"/>
<ListBox IsHitTestVisible="False" Grid.Column="1" VerticalAlignment="Center" >
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<TextBlock x:Name="ContentCategoryTitle" Height="70" Text="{Binding ContentTitle}" Width="460" Margin="5,34,0,0" TextTrimming="WordEllipsis" TextWrapping="NoWrap" FontSize="28" FontFamily="Segoe WP Semibold" Foreground="#FFF7F7F7" VerticalAlignment="Bottom" />
</ListBox>
</Grid>
<Rectangle Fill="#FF585858" Height="1" Margin="0,0,0,0" Width="460" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Is it possible to binding not an ObservableCollection<ContentItemViewModel>, but - ObservableCollection<List<ContentItemViewModel>> ?
Yes that is possible, if you have a collection of collections. Or why not this?
ObservableCollection<ObservableCollection<ContentItemViewModel>>
If you want your UI to be notified of collection changes to your sub collections.
Update
For example:
View Model
public ObservableCollection<ObservableCollection<ContentItemViewModel>> ContentItems
{
get { return _contentItems; }
set { _contentItems = value; // Notify of property change here, this allows you to change the ContentItems reference after view model construction }
}
public MyViewModel()
{
// Populate content items
this.ContentItems = new ObservableCollection
{
new ObservableCollection { new ContentItemViewModel() },
new ObservableCollection { new ContentItemViewModel(), new ContentItemViewModel() }
};
}
View
<ListBox ItemsSource="{Binding ContentItems}" ...>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding MyContentItemViewModelProperty}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>

Categories