Why are ListView and grouped CollectionViewSource not showing any items? - c#

Here is code (minified):
<Page
x:Class="Compote.HubPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Compote"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{Binding HubViewModel, Source={StaticResource Locator}}"
mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<DataTemplate x:Key="DefaultItemTemplate">
<Border Margin="0,0,0,9.5" Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Grid>
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" Height="170"/>
<StackPanel Margin="15,12" VerticalAlignment="Bottom">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14.5" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="{Binding Name}" Style="{ThemeResource CustomListViewItemTextBlockStyle}" />
</StackPanel>
<TextBlock Grid.Column="2" Text="{Binding Price, Converter={StaticResource PriceConverter}}" Style="{ThemeResource CustomListViewItemSecondaryTextBlockStyle}"/>
</Grid>
<TextBlock Text="{Binding Description}" Style="{ThemeResource ListViewItemContentTextBlockStyle}" TextTrimming="CharacterEllipsis" />
<TextBlock Text="{Binding Weight, Converter={StaticResource WeightConverter}}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
</StackPanel>
</Grid>
</Border>
</DataTemplate>
<CollectionViewSource x:Key="CollectionViewSourceCategories" Source="{Binding Categories}" IsSourceGrouped="True" ItemsPath="Items" />
</Page.Resources>
<ListView AutomationProperties.AutomationId="ItemListViewSection4"
AutomationProperties.Name="Items In Group"
SelectionMode="None"
IsItemClickEnabled="True"
ItemsSource="{Binding Source={StaticResource CollectionViewSourceCategories}}"
ContinuumNavigationTransitionInfo.ExitElementContainer="True"
ItemTemplate="{StaticResource DefaultItemTemplate}" AllowDrop="True">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
As you can see, the CollectionViewSource is binded to the ListView and its IsSourceGrouped property is set to True. Categories contains 2 categories with 3 items in each category. But the ListView doesn't show anything, it's totally empty. What's wrong?

you need to add an itemPresenter in the GroupStyle.
<ListView Name="MyList" ItemsSource="{Binding Source={StaticResource CollectionViewSourceCategories}}" Grid.Row="1" Grid.Column="0">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!-- ItemsPresenter -->
<ItemsPresenter />
<TextBlock Text="{Binding Name}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="NAME" DisplayMemberBinding="{Binding name}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
Something else that might be helpful if you're grouping items Is to add a PropertyGroupDescription to your collectionViewSource:
First add this to your declarations:
xmlns:dat="clr-namespace:System.Windows.Data;assembly=PresentationFramework" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
then your CollectionViewSource:
<CollectionViewSource x:Key="CollectionViewSourceCategories" Source="{Binding Categories}">
<CollectionViewSource.GroupDescriptions>
<dat:PropertyGroupDescription PropertyName="Categories" />
</CollectionViewSource.GroupDescriptions>
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Names" />
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
This will group by your category, then sort by names. here's the link explaining it:
https://msdn.microsoft.com/en-us/library/ff407126(v=vs.100).aspx
hope this helps!

You have to bind to the View property of the CollectionViewSource:
ItemsSource="{Binding Source={StaticResource CollectionViewSourceCategories}, Path=View}"

Related

Binding DataGridTemplateColumn in UserControl.Resources

I am currently trying to write a small calendar program in C# WPF.
For the datagrid I have written a userControl.
This works like I want it to work. I will still need to update the optics but for now it is good.
The problem is the code of the DataGridTextColums.. It is all redundant.
So if I want to change something I need to change it everywhere.
<DataGrid x:Name="datagrid"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserResizeColumns="False"
CanUserReorderColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="False"
AutoGenerateColumns="False"
SelectionUnit="Cell"
SelectionMode="Extended"
HeadersVisibility="Column"
Background="Transparent"
BorderBrush="Transparent"
ItemsSource="{Binding DataGridSource.DataGridList, RelativeSource={RelativeSource AncestorType=UserControl}}">
<DataGrid.Columns>
<DataGridTextColumn Header="CW" Width="*" IsReadOnly="True" Binding="{Binding CwCell.Text}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding CwCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding CwCell.BorderColor}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
<DataGridTemplateColumn Header="MO" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding MondayCell.Text}" Margin="5,0,0,0" Width="18"/>
<ItemsControl ItemsSource="{Binding Path=MondayCell.Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="4" Height="4" Margin="0,1,1,1" Fill="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding MondayCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding MondayCell.BorderColor}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip BorderThickness="0" Background="Transparent">
<Grid>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" DataContext="{Binding MondayCell}">
<TextBlock Text="{Binding AppointmentName}"
Background="White" Width="auto" Margin="5,5,5,1"
TextWrapping="Wrap"
FontWeight="Bold"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<TextBlock Text="{Binding AppointmentDescr}"
Background="White" Margin="5,1,5,5"
TextWrapping="Wrap"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<ItemsControl ItemsSource="{Binding Path=Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="4" Height="4" Fill="{Binding Color}" Margin="5,0,5,0"/>
<Border BorderBrush="Silver" BorderThickness="1,0,0,0" Margin="0,0,0,0"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
<DataGridTemplateColumn Header="DI" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Border>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding TuesdayCell.Text}" Margin="5,0,0,0" Width="18"/>
<ItemsControl ItemsSource="{Binding Path=TuesdayCell.Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="4" Height="4" Margin="0,1,1,1" Fill="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="{Binding TuesdayCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding TuesdayCell.BorderColor}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip BorderThickness="0" Background="Transparent">
<Grid>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" DataContext="{Binding TuesdayCell}">
<TextBlock Text="{Binding AppointmentName}"
Background="White" Width="auto" Margin="5,5,5,1"
TextWrapping="Wrap"
FontWeight="Bold"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<TextBlock Text="{Binding AppointmentDescr}"
Background="White" Margin="5,1,5,5"
TextWrapping="Wrap"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<ItemsControl ItemsSource="{Binding Path=Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="4" Height="4" Fill="{Binding Color}" Margin="5,0,5,0"/>
<Border BorderBrush="Silver" BorderThickness="1,0,0,0" Margin="0,0,0,0"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
<!--same for wednesdayCell to sundayCell-->
</DataGrid.Columns>
</DataGrid>
So as you can see each DataGridTemplateColumn binds to a different Cell (Monday to Sunday).
I tried to create a template out of this. If i keep "MondayCell" in the template (like in the Code below), it works. But obviously I cannot use any other source of data except "MondayCell" then.
See:
<UserControl.Resources>
<DataTemplate x:Key="MyCellTemplate">
<Border>
<StackPanel Orientation="Horizontal" Background="Transparent">
<TextBlock Text="{Binding MondayCell.Text}" Margin="5,0,0,0" Width="18"/>
<ItemsControl ItemsSource="{Binding Path=MondayCell.Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" MaxHeight="20"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Ellipse Width="4" Height="4" Margin="0,1,1,1" Fill="{Binding Color}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</DataTemplate>
<Style TargetType="{x:Type DataGridCell}" x:Key="MyCellStyle">
<Setter Property="Background" Value="{Binding MondayCell.BackColor}"/>
<Setter Property="BorderBrush" Value="{Binding MondayCell.BorderColor}"/>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip BorderThickness="0" Background="Transparent">
<Grid>
<Border Background="White" BorderBrush="Black" BorderThickness="1">
<StackPanel Orientation="Vertical" DataContext="{Binding MondayCell}">
<TextBlock Text="{Binding AppointmentName}"
Background="White" Width="auto" Margin="5,5,5,1"
TextWrapping="Wrap"
FontWeight="Bold"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<TextBlock Text="{Binding AppointmentDescr}"
Background="White" Margin="5,1,5,5"
TextWrapping="Wrap"/>
<Border BorderBrush="Silver" BorderThickness="0,1,0,0" Margin="0,1,0,0" />
<ItemsControl ItemsSource="{Binding Path=Addons}" Margin="0,0,7,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Ellipse Width="4" Height="4" Fill="{Binding Color}" Margin="5,0,5,0"/>
<Border BorderBrush="Silver" BorderThickness="1,0,0,0" Margin="0,0,0,0"/>
<TextBlock Text="{Binding Name}" Margin="5,0,0,0"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>
</Grid>
</ToolTip>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="BorderBrush" Value="OrangeRed"/>
</Trigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
Usage in the Datagrid: This works, but only shows the data from MondayCell.
<DataGridTemplateColumn Header="MO" Width="*" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<StaticResource ResourceKey="MyCellTemplate"/>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellStyle>
<StaticResource ResourceKey="MyCellStyle"/>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
How I want to use it, but doesn't work like this:
Any help is appreciated.
For now I keep it redundant, but I would rather use a template so I only need to change 1 piece of code instead of 7.
Thank you for your help!
I would like to present a solution that is based on using a UserControl:
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:StandardColumn Column="{Binding MondayCell}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:StandardColumn Column="{Binding TuesdayCell}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The StandardColumn implementation , for simplicity , can be as following:
<UserControl x:Class="Problem8.StandardColumn"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Problem8"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Name="Parent">
<StackPanel>
<TextBlock Text="{Binding ElementName=Parent,Path=Column}"/>
</StackPanel>
</UserControl>
In this userControl we have a dependency property called Column :
public partial class StandardColumn : UserControl
{
public StandardColumn()
{
InitializeComponent();
}
public static readonly DependencyProperty ColumnProperty =
DependencyProperty.Register("Column", typeof(object), typeof(StandardColumn));
public object Column
{
get { return (object)GetValue(ColumnProperty); }
set { SetValue(ColumnProperty, value); }
}
}
We can also make it even more simple by using the DataContext instead of the Column dependency property.
You could build your columns dynamically using a base string out a txt file and use xamlreader.Parse or persist to disk and then use xamlreader.load.
I answered a similar question a while back but I cannot find the answer.
Create a template as a txt file with placeholders for the parts you want to substitute. Here is the example I use in a sample I wrote:
<?xml version="1.0" encoding="utf-8" ?>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="xxMMMxx" TextAlignment="Center" Grid.ColumnSpan="2"/>
<TextBlock Text="Units" Margin="2,0,2,0" Grid.Row="1"/>
<TextBlock Text="Value" Margin="2,0,2,0" Grid.Row="1" Grid.Column="2" />
</Grid>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding MonthTotals[xxNumxx].Products}" Margin="2,0,2,0" TextAlignment="Right"/>
<TextBlock Text="{Binding MonthTotals[xxNumxx].Total}" Margin="2,0,2,0" TextAlignment="Right" Grid.Column="1"/>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Make that content, copy if newer and you will get a txt file next to your exe you can read in.
In this I have a dynamic datagrid as another txt file as well, but that is not totally necessary.
Here's my code builds and adds columns.
You could just work with the txt file as a string and do string substitution. This shows manipulating it as xml which has the potential for you to insert xelements etc. It is setting attributes whilst you can maybe forget that part and just do the string substitution, xamlreader.parse into a datagrid column and add to the columns collection.
It is substituting month numbers in the binding for a range of months.
If you consider a rolling last n month financial report, this is the general idea. Last month would be 3 now in april. 4 when you run in may.
private void Button_Click(object sender, RoutedEventArgs e)
{
// Get the datagrid shell
XElement xdg = GetXElement(#"pack://application:,,,/dg.txt");
XElement cols = xdg.Descendants().First(); // Column list
// Get the column template
XElement col = GetXElement(#"pack://application:,,,/col.txt");
DateTime mnth = DateTime.Now.AddMonths(-6);
for (int i = 0; i < 6; i++)
{
DateTime dat = mnth.AddMonths(i);
XElement el = new XElement(col);
// Month in mmm format in header
var mnthEl = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value.ToString() == "xxMMMxx");
mnthEl.SetAttributeValue("Text", dat.ToString("MMM"));
string monthNo = dat.AddMonths(-1).Month.ToString();
// Month as index for the product
var prodEl = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value == "{Binding MonthTotals[xxNumxx].Products}");
prodEl.SetAttributeValue("Text",
"{Binding MonthTotals[" + monthNo + "].Products}");
// Month as index for the total
var prodTot = el.Descendants("TextBlock")
.Single(x => x.Attribute("Text").Value == "{Binding MonthTotals[xxNumxx].Total}");
prodTot.SetAttributeValue("Text",
"{Binding MonthTotals[" + monthNo + "].Total}");
cols.Add(el);
}
string dgString = xdg.ToString();
ParserContext context = new ParserContext();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
DataGrid dg = (DataGrid)XamlReader.Parse(dgString, context);
Root.Children.Add(dg);
}
private XElement GetXElement(string uri)
{
XDocument xmlDoc = new XDocument();
var xmltxt = Application.GetContentStream(new Uri(uri));
string elfull = new StreamReader(xmltxt.Stream).ReadToEnd();
xmlDoc = XDocument.Parse(elfull);
return xmlDoc.Root;
}
}
You could potentially build out your entire year view using this sort of approach. Build it as xml or a string. Save to disk. xamlreader.load() it back in as controls off disk.
A similar string manipulation based approach would be to build your control as text. Save as a datatemplate in a resource dictionary. You can load such an uncompiled resource dictionary off disk then and just build once a year. You could build centrally in a small utility app intended just for the purpose and distribute to clients.
This is my second solution. I believe that the selection of the DataGrid as a base have created this complexity. Alternatively we can consider more basic controls.
I am drafting the solution:
The MonthView user control may look as following:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<local:HeaderView Grid.Row="0"/>
<ItemsControl ItemsSource="{Binding Weeks}" Grid.Row="1" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:WeekView/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
The WeekView user control may look as following:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<local:DayView DataContext="{Binding CwCell}" Grid.Column="0"/>
<local:DayView DataContext="{Binding MondayCell}" Grid.Column="1"/>
<local:DayView DataContext="{Binding TuesdayCell}" Grid.Column="2"/>
<local:DayView DataContext="{Binding WednesdayCell}" Grid.Column="3"/>
<local:DayView DataContext="{Binding ThursdayCell}" Grid.Column="4"/>
<local:DayView DataContext="{Binding FridayCell}" Grid.Column="5"/>
<local:DayView DataContext="{Binding FridayCell}" Grid.Column="6"/>
<local:DayView DataContext="{Binding SaturdayCell}" Grid.Column="7"/>
<local:DayView DataContext="{Binding SundayCell}" Grid.Column="8"/>
</Grid>
The DayView user control may look as following:
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding Text}" Width="20" Height="20" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>
The HeaderView user control may look as following:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<local:ColumnHeaderView DataContext="CW" Grid.Column="0" />
<local:ColumnHeaderView DataContext="MO" Grid.Column="1" />
<local:ColumnHeaderView DataContext="TU" Grid.Column="2" />
<local:ColumnHeaderView DataContext="WE" Grid.Column="3" />
<local:ColumnHeaderView DataContext="TH" Grid.Column="4" />
<local:ColumnHeaderView DataContext="FR" Grid.Column="5" />
<local:ColumnHeaderView DataContext="SA" Grid.Column="6" />
<local:ColumnHeaderView DataContext="SU" Grid.Column="7" />
</Grid>
The ColumnHeaderView user control may look as following:
<Border BorderBrush="Black" BorderThickness="1">
<TextBlock Text="{Binding }" Width="20" Height="15" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Border>

How to update TabControl resources?

I have a tab control in my view, bound to an observable collection. But when I call RaisePropertyChanged on it nothing gets updated. The tabs enabled do, but the views inside the tabs do not. How do I refresh the views in my Data templates?
<TabControl IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding DeviceListViewModel.SelectedDevice.TabViewModelsCollection, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding DeviceListViewModel.SelectedDevice.SelectedTabItemVm}" >
<TabControl.Resources>
<DataTemplate DataType="{x:Type vms:HomeViewModel}">
<local:HomeTab/>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:ConfigurationViewModel}">
<Grid>
<local:ConfigurationFileView Visibility="{Binding Configuration, TargetNullValue=Collapsed, FallbackValue=Visible}"/>
<local:ErrorTab Visibility="{Binding Path= Configuration, TargetNullValue=Visible, FallbackValue=Hidden}"/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:ExpansionModulesViewModelFactory}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<DockPanel >
<local:ExpansionModulesList Title="Discovered/Enumerated"
DataContext="{Binding DiscoveredModules}"
/>
<GridSplitter Width="5"/>
<local:ExpansionModulesList Title="User Action Required"
DataContext="{Binding FaultyModules}"
/>
</DockPanel>
</StackPanel>
<DockPanel Grid.Row="1">
<StackPanel Orientation="Horizontal" FlowDirection="RightToLeft" Margin="5" IsEnabled="{Binding IsCommandEnabled}">
<Button Content="Cancel" HorizontalAlignment="Right"
Command="{Binding CancelExpansionCommand }"
ToolTip="Revert all local modifications by refreshing data from the controller." />
<Separator Width="10"/>
<Button Content="Apply" HorizontalAlignment="Center"
Command="{Binding ApplyExpansionCommand }"
ToolTip="Apply all changes to the controller." />
<Separator/>
</StackPanel>
</DockPanel>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type vms:LogViewModel}">
<local:LogView />
</DataTemplate>
<DataTemplate DataType="{x:Type vms:SignalStrengthViewModel}">
<local:SignalStrengthView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Name}" />
<Setter Property="IsEnabled" Value="{Binding IsEnabled}" />
<Setter Property="Header" Value="{Binding Name}" />
</Style>
</TabControl.ItemContainerStyle>
<!--End Device List-->
</TabControl>
actually i can't understand why doesn't update your view, i think you must show me your behind code.
any way you can try:
tabControl.UpdateLayout();
and
tabControl.UpdateDefaultStyle();

WPF : How to bind Button's visibility inside ListBox ItemsControl using selecteditem information ?

I have a list box binds to a ObservableCollection of Items. Each listboxItem contains a few textblocks and a few buttons. I would like to show the buttons inside the listboxItem only when the listbox item is selected or hightlight. If the listbox item is not highlighted, the button should be hidden. I tried to use datatrigger to bind to the IsSelected property. However it does not work. Please advice. thanks
<ListBox Name="LayoutListBox" SelectedItem="{Binding Path=SelectedLayout, Mode=TwoWay}" ItemsSource="{Binding Layouts}" SelectionMode="Single" HorizontalContentAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Gray"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Gray"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border HorizontalAlignment="Stretch" Margin="2" CornerRadius="2" BorderBrush="#80808080" BorderThickness="1" Background="GhostWhite">
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height ="*"/>
<RowDefinition Height ="*"/>
</Grid.RowDefinitions>
<DockPanel Grid.Row="1" Grid.Column="3" DockPanel.Dock="Right">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Visibility="{Binding Path=ViewName, Converter={StaticResource Converter}, ConverterParameter=false}">
<Button ToolTip="Save">
<Image Source="/Common.View;component/LayoutManager/View/Images/PushPin.png" />
</Button>
<Button Click="EditButtonClick" ToolTip="Edit">
<Image Source="/Common.View;component/LayoutManager/View/Images/pencil.png" />
</Button>
<Button Click="DeleteButtonClick" ToolTip="Delete">
<Image Source="/Common.View;component/LayoutManager/View/Images/cross.png" />
</Button>
</StackPanel>
</DockPanel>
</Grid>
</DockPanel>
</Grid>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I attached a simple example to show button in listbox item when you selected. it should have to bind as RelativeSource and have to use Converter
Example:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="booleanVisibleConverter" />
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding ObservableCollection}" Grid.Row="0" SelectedItem="{Binding Path=Item}"
SelectionMode="Single" IsSynchronizedWithCurrentItem="True" Margin="1" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectedIndex="0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Content="{Binding}" />
<Button Content=" X " Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected, Converter={StaticResource booleanVisibleConverter}}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
You can create a style to associate with each of your buttons as follows:
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},
Path=IsSelected}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>

How to make the scrollviewer work in this scenario?

Having some problems with my MVVM Application.
So the scenario is the following:
In my MainWindow.xaml, I have a ContentControl placed in a Grid Column, its content is bind to the CurrentViewModel which will be rendered to the appropriate View (in this case, Overview.xaml).
<ContentControl Grid.Row="1" Grid.Column="1" Content="{Binding CurrentViewModel}">
Within this particular view (Overview.xaml) there are multiple UserControls placed within a StackPanel.
<ScrollViewer CanContentScroll="True" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible">
<StackPanel CanVerticallyScroll="True" CanHorizontallyScroll="True">
<views:DiagramView DataContext="{Binding Path=DiagramViewModel, Source={StaticResource Locator}}" />
<views:IncomeCollectionView DataContext="{Binding Path=IncomesViewModel, Source={StaticResource Locator}}" />
<views:ExpenseCollectionView DataContext="{Binding Path=ExpensesViewModel, Source={StaticResource Locator}}" />
<views:CheckCollectionView DataContext="{Binding Path=ChecksViewModel, Source={StaticResource Locator}}" />
<views:BalanceCollectionView DataContext="{Binding Path=BalancesViewModel, Source={StaticResource Locator}}" />
<views:VacationCollectionView DataContext="{Binding Path=VacationsViewModel, Source={StaticResource Locator}}" />
<views:KHCollectionView DataContext="{Binding Path=KhViewModel, Source={StaticResource Locator}}" />
<views:OctaviaCollectionView DataContext="{Binding Path=OctaviaViewModel, Source={StaticResource Locator}}" />
</StackPanel>
</ScrollViewer>
Each UserControl within this StackPanel has a very similar look (obviously there are more stuff in the XAML). There is no constant value regarding Width or Height within my application.
<ListView ItemsSource="{Binding Source={StaticResource groupedCollection}}" SelectedItem="{Binding CurrentItem}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Items[0].CurrentCategory}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="12" Rows="1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column" Value="{Binding GeneratedColumn}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding EncryptedAmount}" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="Got paid on " />
<TextBlock Text="{Binding Date}" />
</StackPanel>
<Button Content="details"
Command="{Binding Path=DataContext.ShowDialogCommand,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
CommandParameter="QuickEdit"/>
<Button Content="remove" Command="{Binding RemoveCommand}" CommandParameter="Income removed." />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The problem is that I can't seem to make the vertical scrollviewer work. It is displayed because I make it visible, but it's disabled. Obviously the StackPanel is gonna grow indefintely, but isn't there a way for it to calculate how much space is needed? Because most of the content is just cut off right now.
So I tried to put scrollviewer in every possible place, but they're all disabled.
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<ScrollViewer>
<ContentPresenter Cursor="{TemplateBinding Cursor}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So then I tried dropping the StackPanel implementation and tried it with a Grid.
Nope, it doesn't work either.
Obviously I'm missing some basis solution here, but just can't figure it out.
Any ideas would be appreciated, seems like a very common scenario to be honest.
Cheers
<ScrollViewer CanContentScroll="True"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<views:DiagramView DataContext="{Binding Path=DiagramViewModel, Source={StaticResource Locator}}" />
<views:IncomeCollectionView Grid.Row="1" DataContext="{Binding Path=IncomesViewModel, Source={StaticResource Locator}}" />
<views:ExpenseCollectionView Grid.Row="2" DataContext="{Binding Path=ExpensesViewModel, Source={StaticResource Locator}}" />
<views:CheckCollectionView Grid.Row="3" DataContext="{Binding Path=ChecksViewModel, Source={StaticResource Locator}}" />
...etc...
</Grid>
</ScrollViewer>
Edit: The DiagramView UserControl contains the following:
<UserControl x:Class="Expense.Manager.WPF.Views.DiagramView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:pie="clr-namespace:Expense.Manager.WPF.CustomPie"
xmlns:local="clr-namespace:Expense.Manager.WPF.Shared"
mc:Ignorable="d">
<UserControl.Resources>
<local:BoolToBrushConverter x:Key="BoolToBrushConverter" />
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Income this month: " />
<TextBlock>
<TextBlock.Text>
<PriorityBinding FallbackValue="Retrieving data...">
<Binding Path="EncryptedCurrentMonthIncome" Mode="TwoWay" IsAsync="True" />
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<pie:PieChart Data="{Binding PieChartIncomeData, Mode=TwoWay}" Width="250" PieWidth="130" PieHeight="130" Height="140" />
</StackPanel>
<StackPanel Grid.Row="0" Grid.Column="1">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Expenses this month: " />
<TextBlock>
<TextBlock.Text>
<PriorityBinding FallbackValue="Retrieving data...">
<Binding Path="CurrentMonthExpense" Mode="TwoWay" IsAsync="True" />
</PriorityBinding>
</TextBlock.Text>
</TextBlock>
</StackPanel>
<pie:PieChart Data="{Binding PieChartExpenseData, Mode=TwoWay}" Width="250" PieWidth="130" PieHeight="130" Height="140" />
</StackPanel>
<StackPanel Grid.Column="2">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding VacationsLeft}" />
<TextBlock Text=" days left" />
</StackPanel>
<ItemsControl ItemsSource="{Binding VacationsPerYearCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Margin="5, 0, 0, 0" Height="25" Width="4" Fill="{Binding Converter={StaticResource BoolToBrushConverter}}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Bank savings:" />
<TextBlock Text="{Binding BankSavings}" />
</StackPanel>
</StackPanel>
</Grid>
IncomeCollectionView:
<UserControl x:Class="Expense.Manager.WPF.Views.IncomeCollectionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:views="clr-namespace:Expense.Manager.WPF.Views"
mc:Ignorable="d">
<UserControl.Resources>
<CollectionViewSource x:Key="groupedCollection" IsLiveGroupingRequested="True" Source="{Binding Collection}">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="CurrentCategory" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding DisplayName}" Foreground="White" FontWeight="SemiBold" Padding="5" Background="SteelBlue" />
<ListView Grid.Row="1" ItemsSource="{Binding Source={StaticResource groupedCollection}}" SelectedItem="{Binding CurrentItem}">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Items[0].CurrentCategory}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Columns="12" Rows="1" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column" Value="{Binding GeneratedColumn}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding EncryptedAmount}" />
<TextBlock Grid.Row="1" Text="{Binding Date}" />
<Button Grid.Row="2" Content="details"
Command="{Binding Path=DataContext.ShowDialogCommand,
RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
CommandParameter="QuickEdit"/>
<Button Grid.Row="3" Content="remove" Command="{Binding RemoveCommand}" CommandParameter="Income removed." />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
and where it is used:
why is the listview not resizing itself after resizing the window itself?
<ScrollViewer CanContentScroll="True" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<views:IncomeCollectionView Grid.Row="1" DataContext="{Binding Path=IncomesViewModel, Source={StaticResource Locator}}" />
</Grid>
</ScrollViewer>
I tried dropping the StackPanel implementation and tried it with a Grid. Nope, it doesn't work either.
That's almost correct, apart from the last sentence. Using a Grid is half of the answer, because the StackPanel has no functionality to resize its items... you just need to inform the ScrollViewer when to scroll. Take this example:
<ScrollViewer>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Rectangle Fill="Cyan" />
<Rectangle Grid.Row="1" Fill="Green" />
<Rectangle Grid.Row="2" Fill="Red" />
<Rectangle Grid.Row="3" Fill="Blue" />
<Rectangle Grid.Row="4" Fill="Orange" />
<Rectangle Grid.Row="5" Fill="Purple" />
<Rectangle Grid.Row="6" Fill="Yellow" />
</Grid>
</ScrollViewer>
This XAML will make the ScrollViewer ScrollBar appear (once the Window.Height is small enough), but if you remove the RowDefinition.Height values (thereby giving each row a proportion of the whole Grid.Height), you'll see your previous situation where no ScrollBar appears.
Now, none of us want to hard code constant values into our UIs, but you can do this using the Auto setting on the RowDefinition.Height properties instead. Unlike these Rectangles, your controls will all have some Height, so your solution is to set each of your Grid.RowDefinitions like this:
<RowDefinition Height="Auto" />
This will provide your controls with as much space as they need within the Grid and therefore (hopefully) they will have more Height together than the ScrollViewer and therefore the ScrollViewer will display its vertical ScrollBar.

How Does This Grid App Template Scroll without a Scrollviewer? (C#/XAML Windows 8.1)

I've been trying to understand Scrollviewers, and thought I'd take a look at Microsoft's template for a Grid App for 8.1, whose content extends off the screen. What's odd is that there doesn't seem to even be a Scrollviewer in the XAML page. Can anyone tell me what is enabling the scrolling?
<Page
x:Name="pageRoot"
x:Class="GridApp.GroupedItemsPage"
DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:GridApp"
xmlns:data="using:GridApp.Data"
xmlns:common="using:GridApp.Common"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<x:String x:Key="ChevronGlyph"></x:String>
<!--
Collection of grouped items displayed by this page, bound to a subset
of the complete item list because items in groups cannot be virtualized
-->
<CollectionViewSource
x:Name="groupedItemsViewSource"
Source="{Binding Groups}"
IsSourceGrouped="true"
ItemsPath="Items"
d:Source="{Binding Groups, Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}"/>
</Page.Resources>
<!--
This grid acts as a root panel for the page that defines two rows:
* Row 0 contains the back button and page title
* Row 1 contains the rest of the page layout
-->
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Horizontal scrolling grid -->
<GridView
x:Name="itemGridView"
AutomationProperties.AutomationId="ItemGridView"
AutomationProperties.Name="Grouped Items"
Grid.RowSpan="2"
Padding="116,137,40,46"
ItemsSource="{Binding Source={StaticResource groupedItemsViewSource}}"
SelectionMode="None"
IsSwipeEnabled="false"
IsItemClickEnabled="True"
ItemClick="ItemView_ItemClick">
<GridView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Width="250" Height="250">
<Border Background="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}">
<Image Source="{Binding ImagePath}" Stretch="UniformToFill" AutomationProperties.Name="{Binding Title}"/>
</Border>
<StackPanel VerticalAlignment="Bottom" Background="{ThemeResource ListViewItemOverlayBackgroundThemeBrush}">
<TextBlock Text="{Binding Title}" Foreground="{ThemeResource ListViewItemOverlayForegroundThemeBrush}" Style="{StaticResource TitleTextBlockStyle}" Height="60" Margin="15,0,15,0"/>
<TextBlock Text="{Binding Subtitle}" Foreground="{ThemeResource ListViewItemOverlaySecondaryForegroundThemeBrush}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap" Margin="15,0,15,10"/>
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid GroupPadding="0,0,70,0"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Margin="0,0,0,2">
<Button Foreground="{ThemeResource ApplicationHeaderForegroundThemeBrush}"
AutomationProperties.Name="Group Title"
Click="Header_Click"
Style="{StaticResource TextBlockButtonStyle}" >
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" Margin="0,-11,10,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
<TextBlock Text="{StaticResource ChevronGlyph}" FontFamily="Segoe UI Symbol" Margin="0,-11,0,10" Style="{StaticResource SubheaderTextBlockStyle}" TextWrapping="NoWrap" />
</StackPanel>
</Button>
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</GridView.GroupStyle>
</GridView>
<!-- Back button and page title -->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"/>
<TextBlock x:Name="pageTitle" Text="{StaticResource AppName}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
</Grid>
</Grid>
If we go check out the default GridView template and look for the ItemsPresenter we see it's embedded in a ScrollViewer at the template level. Since now we know there's one there, if we look up towards the top in the Setter declarations we've got some Properties available to us to interact with that ScrollViewer from the GridView itself by seeing;
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled" />
<Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
<Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False" />
<Setter Property="ScrollViewer.ZoomMode" Value="Disabled" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="ScrollViewer.BringIntoViewOnFocusChange" Value="True" />
So if we wanted that GridView to not scroll anymore we could tell it not to like;
<GridView ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
since it's set to "Auto" at the template level by default.
That's the thing about templates, sometimes it just takes digging one level deeper. Hope this helps, cheers.

Categories