How to get ControlTemplate not to override DataTemplate? - c#

Similar to gmail's Select button, I wanted to create a ComboBox for the ListView which allows the user to quickly select entries of their choosing (ex. All, None, Read, Unread). However, the selected value would display a tri-state CheckBox equivalent to All, Some, or None of the entries being selected. I succeeded in doing so. Below is the xaml for an example Window utilizing this feature(*):
<Window x:Class="WPFTest.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wpfTest="clr-namespace:WPFTest.ViewModels"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Mvvm;assembly=Microsoft.Practices.Prism.Mvvm.Desktop"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFTest.Models"
mc:Ignorable="d" Title="WPF Test" Height="221.256" Width="605"
d:DataContext="{d:DesignInstance wpfTest:MainWindowViewModel, IsDesignTimeCreatable=True}"
prism:ViewModelLocator.AutoWireViewModel="True" WindowStartupLocation="CenterScreen">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/WPFTest;Component/Resources/Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ListView
ItemsSource="{Binding Entries}"
SelectedValue="{Binding SelectedEntry}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ScrollViewer.CanContentScroll="True"
SelectionMode="Single"
Margin="10">
<ListView.View>
<GridView>
<GridViewColumn Width="Auto">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox
IsChecked="{Binding Selected}"
Command="{Binding DataContext.RowSelectedCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
HorizontalAlignment="Center"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
<GridViewColumnHeader>
<ComboBox
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"
ItemTemplateSelector="{DynamicResource itemTemplateSelector}"
HorizontalAlignment="Stretch"
Margin="0,0,0,0"
VerticalAlignment="Stretch"
Width="44"
Height="34"
FontSize="20"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Left">
<ComboBox.Resources>
<DataTemplate x:Key="selectedTemplate">
<TextBlock
x:Name="displayText"
Text="{Binding DataContext.Options.SelectedDisplay, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
FontSize="20"
Height="22"/>
</DataTemplate>
<DataTemplate x:Key="dropDownTemplate">
<TextBlock Text="{Binding}" FontSize="12"/>
</DataTemplate>
<local:ComboBoxItemTemplateSelector
x:Key="itemTemplateSelector"
SelectedTemplate="{StaticResource selectedTemplate}"
DropDownTemplate="{StaticResource dropDownTemplate}"/>
</ComboBox.Resources>
</ComboBox>
</GridViewColumnHeader>
</GridViewColumn>
<GridViewColumn
Width="Auto"
DisplayMemberBinding="{Binding Type, Mode=OneWay}"
Header="Type"/>
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
Recently I was asked to make a style for every ComboBox on our screens - changing their backgrounds. Because I'm on Windows8, setting the Background alone isn't enough. Using this tutorial I was able to create the ControlTemplate to get the correct behavior, with one minor error fix:
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="True"/>
<!-- Comment out the following, it throws an error. -->
<!--<Condition>
<Condition.Value>
<sys:Boolean>False</sys:Boolean>
</Condition.Value>
</Condition>-->
</MultiTrigger.Conditions>
And usage:
<Style
TargetType="{x:Type ComboBox}">
...
<Setter
Property="Template"
Value="{StaticResource ComboBoxStyle1}" />
</Style>
This successfully styles the ComboBox Background. However, revisiting the former screen, I noticed that this breaks my gmail-like display.
How can I get this ControlTemplate and the dynamic DataTemplate to cooperate?
(*) ViewModels and Models can be provided if necessary for a solution. Or see full working example.

I'm not sure why you doing so complicated ComboBox - you defined ItemTemplateSelector twice...
Ok - here is my 2 cents: ComboBox is lookless control. It based on ControlTemplate target type = ComboBox. Inside ComboBox ControlTemplate you will find ContentPresenter. Whatever coming into Content of ContentPresenter could be styled with DataTemplate. Generally - when you define DataTemplate it wrap only ContentPresenter or ItemsPresenter for range based controls - not the whole ControlTemplate obviously.
So if you want to change 'Selected' template for ComboBox is ok but all other data should be defined via DataTemplate for this type {x:Type local:SomeType} that will be used by ComboBox.
Also - consider using #galakt suggestion: use Style with TargetType - it easy to read, refactor, find, understand...

Color the Background
As per the OP, following this tutorial, you generate the ControlTemplate.
To do this, you can right-click on the ComboBox element in design mode
in Visual Studio 2012 or 2013 and select the “Edit template” option
and then the “Edit a copy…” option.
Again note the bug fix from the OP. Changing the background can then be done by:
<Border
x:Name="templateRoot"
BorderBrush="#FFACACAC"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True"
Background="{StaticResource MyComboBackgroundBrush}"> <!-- option 1 -->
<!-- <Border.Background> -->
<!-- option 2 -->
<!-- <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFF0F0F0" Offset="0"/>
<GradientStop Color="#FFE5E5E5" Offset="1"/>
</LinearGradientBrush>-->
<!-- option 3 -->
<!-- <SolidColorBrush Color="Yellow"/> -->
<!-- </Border.Background>
<Border x:Name="splitBorder" BorderBrush="Transparent" BorderThickness="1" HorizontalAlignment="Right" Margin="0" SnapsToDevicePixels="True" Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}">
<Path x:Name="Arrow" Data="F1M0,0L2.667,2.66665 5.3334,0 5.3334,-1.78168 2.6667,0.88501 0,-1.78168 0,0z" Fill="#FF606060" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center"/>
</Border> -->
</Border>
Interact with the DataTemplate
In the resource file, following the above instructions, you declared:
<ControlTemplate x:Key="ComboBoxControlTemplateBasic" TargetType="{x:Type ComboBox}">
...
<ContentPresenter
x:Name="contentPresenter"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
... />
...
</ControlTemplate>
Create a copy of it with the following change, where selectedTemplate is the key of the DataTemplate you want to cooperate with the ControlTemplate:
<ControlTemplate x:Key="ComboBoxControlTemplateHeader" TargetType="{x:Type ComboBox}">
...
<ContentPresenter
x:Name="contentPresenter"
ContentTemplate="{DynamicResource selectedTemplate}"
... />
...
</ControlTemplate>
Declare the appropriate styles:
<Style
TargetType="{x:Type ComboBox}">
<Setter Property="Template"
Value="{StaticResource ComboBoxControlTemplateBasic}" />
<!-- other generic style setters -->
</Style>
<Style
x:Key="ComboBoxHeader"
x:Name="ComboBoxHeader"
TargetType="{x:Type ComboBox}"
BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="Template"
Value="{StaticResource ComboBoxControlTemplateHeader}" />
<Setter Property="ItemTemplateSelector"
Value="{DynamicResource itemTemplateSelector}"/>
<!-- other specific style setters -->
</Style>
Results
Every ComboBox shares the same look.
The dynamic use of DataTemplate selectedTemplate allows each ListView header gmail-like ComboBox to have the same look with unique binding values.
Take for example the OP ComboBox header plus the following ComboBox with the same item source:
<ComboBox
HorizontalAlignment="Left"
Margin="10,152,0,0"
VerticalAlignment="Top"
Width="120"
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"/>
<GridViewColumnHeader>
<ComboBox
ItemsSource="{Binding Options.Items}"
SelectedValue="{Binding Options.SelectedItem}"
Style="{StaticResource ComboBoxHeader}">
<ComboBox.Resources>
<DataTemplate x:Key="selectedTemplate">
<TextBlock
x:Name="displayText"
Text="{Binding DataContext.Options.SelectedDisplay, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
FontSize="20"
Height="22"/>
</DataTemplate>
<DataTemplate x:Key="dropDownTemplate">
<TextBlock Text="{Binding}" FontSize="12"/>
</DataTemplate>
<local:ComboBoxItemTemplateSelector
x:Key="itemTemplateSelector"
SelectedTemplate="{StaticResource selectedTemplate}"
DropDownTemplate="{StaticResource dropDownTemplate}"/>
</ComboBox.Resources>
</ComboBox>
</GridViewColumnHeader>

Related

Using {x: Bind} to bind to an XAML property, i.e. replacing {TemplateBinding XAMLProperty}

It is stated in MSDN that
Starting with Windows 10, version 1809, you can use the x:Bind markup extension anywhere you use TemplateBinding in a ControlTemplate.
However, when I try to replace TemplateBinding with {x:Bind} whilst defining the style of a custom control, as so,
<Style TargetType="local:PomodoroTimer" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:PomodoroTimer">
<Grid Width="300" Height="300" Background="{x:Bind Background}">
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I get the following error: Unable to resolve symbol 'Background'. What am I missing?
x:Bind needs code-behind. (see here)
So, thanks to MainWindow.xaml.cs, this works:
<Window
x:Class="Bindings.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Bindings"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.Resources>
<Style
x:Key="CustomButtonStyle"
TargetType="Button">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
BorderBrush="{x:Bind BorderBrush, Mode=OneWay}"
BorderThickness="{x:Bind BorderThickness, Mode=OneWay}">
<ContentControl Content="{x:Bind Content, Mode=OneWay}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</Grid.Resources>
<Button
BorderBrush="SkyBlue"
BorderThickness="1"
Content="Custom Button"
Style="{StaticResource CustomButtonStyle}" />
</Grid>
</Window>
For custom (templated) controls, I'd go with:
Text="{TemplateBinding Text}"
or
Text="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
for TwoWay bindings.
If you want to do x:Bind inside the ControlTemplate, this answer might help.

TabControl.Resource DataTemplate Use Icon Instead of Text

I have a project that adds tabs to the view using a TabControl with DataTemplates like so:
<TabControl Name="dcTabControl"
ItemsSource="{Binding Tabs}"
SelectedItem="{Binding SelectedTabViewModel}"
Height="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=DataContext.MainContentHeight}">
<TabControl.Resources>
<!-- Removed numerous other tabs to save space -->
<!-- System Setup tab -->
<DataTemplate DataType="{x:Type vm:SystemSetupViewModel}">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<v:SystemSetupUserControl />
</ScrollViewer>
</DataTemplate>
<!-- About tab -->
<DataTemplate DataType="{x:Type vm:AboutViewModel}">
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<v:AboutUserControl />
</ScrollViewer>
</DataTemplate>
</TabControl.Resources>
</TabControl>
Each ViewModel has a Header property that is used to populate the text of the tab (e.g. "About").
I now have a requirement to change the "About" text to an icon. I have tried this but it doesn't change anything.
<!-- About tab -->
<DataTemplate DataType="{x:Type vm:AboutViewModel}">
<TabItem>
<TabItem.Header>
<Image Name="AboutTabImage" Height="auto" Width="auto" Source="Images/About.png" />
</TabItem.Header>
<TabItem.Content>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto">
<v:AboutUserControl />
</ScrollViewer>
</TabItem.Content>
</TabItem>
</DataTemplate>
How can I get an icon in place of the text?
UPDATE Adding code to show how Header property is bound to Tab.
The Header is bound to the Tab using this Style
<!-- Standard Tab Style -->
<Style x:Key="TabStyle" TargetType="{x:Type TabItem}">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="Width" Value="Auto" />
<Setter Property="Padding" Value="10,5,10,5" />
</Style>
I am now thinking I have to create a new style to use an icon instead of text, but not sure how I would apply that style to the data template.
You may add a DataTrigger to the TabItem Style that changes the Header to an Image if the Header property contains the string "About":
<Style TargetType="TabItem">
...
<Setter Property="Header" Value="{Binding Header}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Header}" Value="About">
<Setter Property="Header">
<Setter.Value>
<Image Source="Images/About.png"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>

Wrappanel inside ScrollViewer in two different libraries

I'm new in wpf and mvvm, so i desided ask some help. And sorry, but english is not my native language.
I have main application for displaying some documents. Each document is an external dll + xml-file with data.
In main application i have XAML:
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="DarkGray">
<Border Margin="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White" Padding="20">
<ContentControl x:Name="ccCurrentView" cal:View.Model="{Binding Path=CurrentView}"/>
</Border>
</ScrollViewer>
In ContentControl i display view of my document as UserControl from dll. And we use MVVM, so XAML of document is something like that:
<UserControl>
<StackPanel>
<UserControl_Type1 />
<UserControl_Type2 />...
</StackPanel>
<UserControl_Type3 />
</UserControl>
Any of these UserControl_TypeXXX can be inside its own dll.
Now users ask me replace StackPanel with WrapPanel for some type of UserControl. And, when user resize main application, some controls first wrap theirs elements and only then show scrollbars for all document.
But according to the information i've read WrapPanel doesn't wraps inside ScrollViewer.
How can i achieve this behavior if i don't have widht and height from main application and can't predict which UserControl inside my document should wrap theirs elements?
I found this article about xaml anti-patterns and it helps me a lot.
In my case I switch between two content template. One with ScrollViewer for old documents, another - without.
In Resources:
<DataTemplate x:Key="ResizableContent" >
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="DarkGray">
<Border Margin="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White" Padding="20">
<ContentControl x:Name="ccCurrentView" cal:View.Model="{Binding Path=CurrentView}"/>
</Border>
</Border>
</DataTemplate>
<DataTemplate x:Key="NotResizableContent" >
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Background="DarkGray">
<Border Margin="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="White" Padding="20">
<ContentControl x:Name="ccCurrentView" cal:View.Model="{Binding Path=CurrentView}"/>
</Border>
</ScrollViewer>
</DataTemplate>
In MainPanel:
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource NotResizableContent}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsResizable}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource ResizableContent}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>

ComboBox with fixed Header

I need to show a default text in my ComboBox, this text must not changed also when the user select an item of the Combobox, actually for do this I've created this structure:
<ComboBox ItemsSource="{Binding AvailableNations}" Width="160" Height="55" Margin="0, 0, 0, 15"
Text="Select Countries" IsEditable="True">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
this display as default text Select Countries but if I select an item the default text will disappear and the item selected will be displayed, how can I fix this?
You could use a Combined Template (ref post)
<Window.Resources>
<ResourceDictionary>
<DataTemplate x:Key="NormalItemTemplate" >
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Item.Name}" />
</DataTemplate>
<DataTemplate x:Key="SelectionBoxTemplate" >
<TextBlock>Select Countries</TextBlock>
</DataTemplate>
<DataTemplate x:Key="CombinedTemplate">
<ContentPresenter x:Name="Presenter"
Content="{Binding}"
ContentTemplate="{StaticResource NormalItemTemplate}" />
<DataTemplate.Triggers>
<DataTrigger
Binding="{Binding RelativeSource={RelativeSource FindAncestor,ComboBoxItem,1}}"
Value="{x:Null}">
<Setter TargetName="Presenter" Property="ContentTemplate"
Value="{StaticResource SelectionBoxTemplate}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ComboBox ItemsSource="{Binding AvailableNations}"
SelectedItem="{Binding SelectedNation}"
ItemTemplate="{StaticResource CombinedTemplate}"
Width="160" Height="55" Margin="0, 0, 0, 15" >
</ComboBox>
</Grid>
The way it works is described in the original answer. Note that the suggested solution will only work when IsEditable is set to false, I assume that won't be a problem in your case. Second, to get the text displayed at start up I bound SelectedItem (e.g. to the first item in the collection).
From the comments, it sounds like you just want the Select Countries text to display at all times, even when an item is selected.
Personally I would just go the simple route and place a TextBox on top of the ComboBox, and hide the Display Text of the ComboBox by using a Transparent Foreground color.
Here's a quick example demonstrating it :
<Grid>
<ComboBox SelectedIndex="1" Foreground="Transparent">
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<!-- Make sure ComboBoxItems don't have transparent text -->
<Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.ControlTextBrushKey}}" />
</Style>
</ComboBox.Resources>
<ComboBoxItem>Test 1</ComboBoxItem>
<ComboBoxItem>Test 2</ComboBoxItem>
<ComboBoxItem>Test 3</ComboBoxItem>
</ComboBox>
<TextBlock Text="Select Countries" Margin="4,3" IsHitTestVisible="False" />
</Grid>
And the results (note that SelectedIndex = 1)
I'm sure there's other ways too, such as overwriting the way it paints the display text, or changing the control template, but this seemed like the easiest to me.

Binding to data breaking on VirtualizingStackPanel

First of all, a disclaimer, I'm working with .net 3.5's virtualizingstackpanel. If you get different behavior in future versions let me know. It's relatively simple to set up a test case with listviews that you can test this against.
I have an itemcontainer style in a virtualizingstackpanel that binds the property IsSelected to the viewmodel.
When I Select an unselected item in the view model that is off screen, and then scroll to that item, both the datacontext (viewmode) and the actual listviewitem have the IsSelected Property as true (expected behavior). The trigger is properly applied to the listviewitem highlighting it.
However, when I deselect the datacontext for an item that is not in view and then scroll down until the item is in view, upon reaching the item and creating it, the item's datacontext now has IsSelected = true and the listviewitem's IsSelected property is also true, so the listviewitem ends up with a selection rectangle from the trigger(incorrect behavior).
It's almost as if the ListViewItem's Properties are all restored on creation of the item ( this makes sense to me, but then they should bind the datacontext's values to the item afterward).
But that doesn't seem to be happening. Moreover, after failing to deselect the item and scrolling back to find it selected. If i then select/desect it, the binding has no effect on the item.
I can see no logical reason why it would work when selecting an item in the viewmodel that is offscreen and not when I Deselect an item offscreen. In both cases, the newly created item should need to be rebound to the current value of the viewmodel. However, one works and the other doesn't.
Edit:
Ah ok, so I just can't use recycling mode and binding it seems. Thanks #devhedgehog. Would give you the bounty but you need an answer. I swear I tried that earlier, but maybe I was not handling click events in the bound listview before so that I was breaking the binding on physical selection or something. I do remember attempting both modes at one point, but probably had something else interfering so it wouldn't work. Anyway it works now.
Since you mentioned it, I would like to preferably avoid keeping unnecessary code and inherit from virtualizingstackpanel instead of virtualizing panel. But I want to be able to set the horizontal scroll extent, which requires me to reimplement Iscrollinfo. However, I was having trouble getting virtualizingstackpanel to interact nicely with iscrollinfo.
<ListView
x:Name="TestLV"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Background="Green"
ItemsSource="{Binding Path=AddedItems, Mode=OneWay}"
SnapsToDevicePixels="True"
VirtualizingStackPanel.VirtualizationMode="Recycling"
VirtualizingStackPanel.IsVirtualizing="true"
ScrollViewer.IsDeferredScrollingEnabled="False"
Grid.Column ="4"
MouseDown="TestLV_MouseDown"
>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=OneWay}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid
x:Name="SignalGrid"
Background="Transparent"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border
Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ContentPresenter
x:Name="PART_Header"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
/>
</Border>
<ItemsPresenter
x:Name="ItemsHost"
Grid.Row="1"
Grid.Column="0"
/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="false">
<Setter
TargetName="SignalGrid"
Property="Background"
Value="Transparent"
/>
</Trigger>
<Trigger Property="IsSelected"
Value="true">
<Setter
TargetName="SignalGrid"
Property="Background"
Value="Navy"
/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
<!--<Components:VirtualizingTilePanel
ChildSize="{Binding Path=GraphHeight}"
/>-->
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.Template>
<ControlTemplate>
<Grid >
<ScrollViewer
>
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</ListView.Template>
<!--Template Defining the layout of items in this treeview-->
<ListView.Resources>
<HierarchicalDataTemplate
ItemsSource ="{Binding Path = bits}"
DataType="{x:Type ViewModels:BusViewModel}"
>
<Grid>
<Components:CenteredTextBlock
x:Name="CommentTextBlock"
Foreground="Black"
BorderThickness="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderThickness}"
BorderBrush="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderBrush}"
HorizontalAlignment="Stretch"
Height="{Binding ElementName=graph_viewer, Path=GraphHeight, Mode=OneWay}"
>
<Components:CenteredTextBlock.MainText>
<MultiBinding Converter="{StaticResource StringConcatConverter}">
<Binding Path="Alias" />
<Binding Path="SignalValueAtPrimaryMarker" />
</MultiBinding>
</Components:CenteredTextBlock.MainText>
</Components:CenteredTextBlock>
</Grid>
</HierarchicalDataTemplate>
<DataTemplate
DataType="{x:Type ViewModels:BitViewModel}"
>
<Grid>
<Components:CenteredTextBlock
Foreground="Black"
BorderThickness="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderThickness}"
BorderBrush="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderBrush}"
HorizontalAlignment="Stretch"
Height="{Binding ElementName=graph_viewer, Path=GraphHeight, Mode=OneWay}">
<Components:CenteredTextBlock.MainText>
<MultiBinding Converter="{StaticResource StringConcatConverter}">
<Binding Path="Alias" />
<Binding Path="SignalValueAtPrimaryMarker" />
</MultiBinding>
</Components:CenteredTextBlock.MainText>
</Components:CenteredTextBlock>
</Grid>
</DataTemplate>
<DataTemplate
DataType="{x:Type ViewModels:SelectableItemViewModel}"
>
<Grid>
<Components:CenteredTextBlock
Foreground="Red"
BorderThickness="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderThickness}"
BorderBrush="{Binding RelativeSource ={RelativeSource AncestorType={x:Type ListView}}, Path=BorderBrush}"
HorizontalAlignment="Stretch"
Height="{Binding ElementName=graph_viewer, Path=GraphHeight, Mode=OneWay}"
MainText="{Binding Path = FullName}"
/>
</Grid>
</DataTemplate>
</ListView.Resources>
</ListView>
It seems strange that this question actually appears to have been answered, yet is listed as not having an answer. So I will post dev hedgehog's comment/answer here.
Please use standard VirtualizingStackPanel without your custom measure
logic. There is nothing you added special in your logic that
VirtualizingStackPanel cant do. And RecyclingMode should not be
Recycle but instead leave it out or change to Standard.

Categories

Resources