WPF TreeViewItem Control Template Partially applied? - wpf

I know a ControlTemplate is suppose to replace the default one entirely and this seems to work when not using a HierarchicalDataTemplate. However using a HierarchicalDataTemplate my control template seems to be partially used - the TreeViewItem is the control I specified containing an image etc. BUT still appears as a node with the default expander to show its children - not specified in my Template (I want my children to always be shown, but thats beside the point). It looks like this:
<TreeView>
<TreeView.Resources>
<Style x:Key="MyNodeStyle" TargetType="TreeViewItem">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsExpanded" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<Border CornerRadius="8" BorderThickness="1" Padding="2" Margin="4, 6" BorderBrush="{StaticResource itemBorderBrush}" Background="{StaticResource itemBackgroundBrush}" x:Name="border">
<DockPanel LastChildFill="False">
<StackPanel Orientation="Vertical" DockPanel.Dock="Top" Height="80">
<TextBlock Text="{Binding Path=DisplayValue}" HorizontalAlignment="Center" FontWeight="Bold"/>
<Image Source="MyNode.png" Stretch="None"/>
<TextBlock Text="{Binding Path=Notes}" TextWrapping="Wrap" Width="150"/>
</StackPanel>
</DockPanel>
</Border>
<ItemsPresenter />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<HierarchicalDataTemplate DataType="{x:Type src:MyNode}" ItemsSource="{Binding Path=Children}" >
<TreeViewItem Style="{StaticResource MyNodeStyle}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
<!-- Arrange the root items horizontally. -->
<TreeView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True" Orientation="Horizontal" HorizontalAlignment="Center" />
</ItemsPanelTemplate>
</TreeView.ItemsPanel>
</TreeView>
For some reason only when using a HierarchicalDataTemplate the ItemsPanel and Setter does not seem to be applied and the children are presented in the default expander. How did that expander get there when I am using my own ControlTemplate!?##$

I don't think you should put the TreeViewItem inside your HierarchicalDataTemplate.
Try this:
<HierarchicalDataTemplate DataType="{x:Type src:MyNode}" ItemsSource="{Binding Path=Children}" >
<StackPanel Orientation="Vertical" DockPanel.Dock="Top" Height="80">
<TextBlock Text="{Binding Path=DisplayValue}" HorizontalAlignment="Center" FontWeight="Bold"/>
<Image Source="MyNode.png" Stretch="None"/>
<TextBlock Text="{Binding Path=Notes}" TextWrapping="Wrap" Width="150"/>
</StackPanel>
</HierarchicalDataTemplate>
Now, your template becomes:
<ControlTemplate TargetType="TreeViewItem">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<Border CornerRadius="8" BorderThickness="1" Padding="2" Margin="4, 6" x:Name="border">
<DockPanel LastChildFill="False">
<ContentPresenter ContentSource="Header" />
</DockPanel>
</Border>
<ItemsPresenter />
</StackPanel>
</ControlTemplate>
Is that how you intended it to look?
Edit: the original expanders are probably there because you only use your style for child items - make your style the ItemContainerStyle for the treeview:
<Window.Resources>
<Style x:Key="MyNodeStyle" TargetType="TreeViewItem">
....
<TreeView ItemContainerStyle="{StaticResource MyNodeStyle}">

Related

Distribute Labels evenly in certain space [duplicate]

I have an ItemsControl, the ItemsPanel is made by a DockPanel.
Inside of the DockPanel, I can have one, two, or three buttons. The problem arises from the width of the buttons: I want the three elements with the same size, but the elements take the size that they need (the last element take the excess width because LastChildFill is true).
Can I give the buttons the same width without providing their size manually?
<ItemsControl ItemTemplate="{StaticResource Template1}" ItemsSource="{Binding Path=options, Mode=OneWay}" ItemsPanel="{StaticResource Panel1}" HorizontalContentAlignment="Stretch"/>
<ItemsPanelTemplate x:Key="Panel1">
<DockPanel Height="Auto" Width="Auto" LastChildFill="True"/>
</ItemsPanelTemplate>
<DataTemplate x:Key="BasicasTemplateOpciones" DataType="{x:Type local:MyOption}">
<Grid HorizontalAlignment="Stretch">
<Button DataContext="{Binding}" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</DataTemplate>
A UniformGrid with a single row will do what you want:
<ItemsPanelTemplate x:Key="Panel1">
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
Example:
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<ItemsPanelTemplate x:Key="Panel1">
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
<Style TargetType="ItemsControl" x:Key="ICStyle">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="2" />
</Style>
</Style.Resources>
<Setter Property="ItemsPanel" Value="{StaticResource Panel1}" />
</Style>
</StackPanel.Resources>
<ItemsControl Style="{StaticResource ICStyle}">
<Button>Foo</Button>
</ItemsControl>
<ItemsControl Style="{StaticResource ICStyle}">
<Button>Foo</Button>
<Button>Bar</Button>
</ItemsControl>
<ItemsControl Style="{StaticResource ICStyle}">
<Button>Foo</Button>
<Button>Bar</Button>
<Button>Baz</Button>
</ItemsControl>
</StackPanel>

Fill all available space in ItemsComtrol with same width size of elements

I have an ItemsControl, the ItemsPanel is made by a DockPanel.
Inside of the DockPanel, I can have one, two, or three buttons. The problem arises from the width of the buttons: I want the three elements with the same size, but the elements take the size that they need (the last element take the excess width because LastChildFill is true).
Can I give the buttons the same width without providing their size manually?
<ItemsControl ItemTemplate="{StaticResource Template1}" ItemsSource="{Binding Path=options, Mode=OneWay}" ItemsPanel="{StaticResource Panel1}" HorizontalContentAlignment="Stretch"/>
<ItemsPanelTemplate x:Key="Panel1">
<DockPanel Height="Auto" Width="Auto" LastChildFill="True"/>
</ItemsPanelTemplate>
<DataTemplate x:Key="BasicasTemplateOpciones" DataType="{x:Type local:MyOption}">
<Grid HorizontalAlignment="Stretch">
<Button DataContext="{Binding}" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
<TextBlock HorizontalAlignment="Right" VerticalAlignment="Stretch"/>
</StackPanel>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</DataTemplate>
A UniformGrid with a single row will do what you want:
<ItemsPanelTemplate x:Key="Panel1">
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
Example:
<StackPanel Orientation="Vertical">
<StackPanel.Resources>
<ItemsPanelTemplate x:Key="Panel1">
<UniformGrid Rows="1" />
</ItemsPanelTemplate>
<Style TargetType="ItemsControl" x:Key="ICStyle">
<Style.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="2" />
</Style>
</Style.Resources>
<Setter Property="ItemsPanel" Value="{StaticResource Panel1}" />
</Style>
</StackPanel.Resources>
<ItemsControl Style="{StaticResource ICStyle}">
<Button>Foo</Button>
</ItemsControl>
<ItemsControl Style="{StaticResource ICStyle}">
<Button>Foo</Button>
<Button>Bar</Button>
</ItemsControl>
<ItemsControl Style="{StaticResource ICStyle}">
<Button>Foo</Button>
<Button>Bar</Button>
<Button>Baz</Button>
</ItemsControl>
</StackPanel>

creating Icon View mode for ListView WPF

I'm Trying to change listView GridView to IconView, as you see in the screenshot, each item is taking a row.
Style XAML
<UserControl.Resources>
<Style x:Key="FileItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Width" Value="50"/>
<Setter Property="Margin" Value="5,5,5,5"/>
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" Width="50">
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="2.5"/>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentPresenter />
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
ListView XAML
<ListView ItemContainerStyle="{DynamicResource FileItemStyle}" HorizontalAlignment="Left" Height="194.667" Margin="11,77.666,0,0" VerticalAlignment="Top" Width="368.667" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" UseLayoutRounding="False">
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Left" Height="50">
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" Height="50" VerticalAlignment="Stretch" Width="50" CornerRadius="2.5"/>
<StackPanel>
<Image x:Name="Img" Source="BtnImg/Computer.png" Stretch="None" Margin="9,0,9,0" Width="32" Height="32"/>
<TextBlock x:Name="PCName" Margin="0" TextWrapping="Wrap" Height="18" HorizontalAlignment="Stretch" TextAlignment="Center"><Run Text="{Binding Content}"/></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
<ListBoxItem Content="ddd"/> <!--**-->
<ListViewItem Content="zczxcz"/>
</ListView>
I've tried to use MDSN example : How to: Create a Custom View Mode for a ListView and modify it to get what I need, but it didn't work with me, I actually couldn't understand the example clearly, anyone can Simplify how can I create a View mode? Do I have to create an overrided ViewBase class?
Thanks in advance
Using the same exact Code Behind as My Answer to your previous question:
<Style x:Key="FileItemStyle" TargetType="{x:Type ListViewItem}">
<Setter Property="Margin" Value="5,5,5,5"/>
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Height="50" >
<Border x:Name="border" BorderBrush="{x:Null}" BorderThickness="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" CornerRadius="2.5"/>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ContentPresenter/>
</StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then:
<ListView ItemsSource="{Binding}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedItem="{Binding SelectedComputer, RelativeSource={RelativeSource AncestorType=Window}}"
ItemContainerStyle="{StaticResource FileItemStyle}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel>
<TextBlock DockPanel.Dock="Bottom" Text="{Binding Name}"/>
<Rectangle Height="32" Width="32" Fill="Blue"/>
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Result:
Remove the hardcoded Width and Heights
Replace the blue rectangle for your Image.
Add some Triggers in the ControlTemplate so that you get highlighting when IsSelected="True"
Simply change the ItemsPanel of any ItemsControl in order to define how items are laid out.
Using a WrapPanel, you get a layout similar to Windows Explorer, where items are placed horizontally until there is no more horizontal space and then another "row" is created. Run the example and resize the Window to see this.
Bottom line: NO, you don't need custom code to customize the UI in WPF. It can be done with the existing controls and some XAML. Please read the "Alternatives to Writing a New Control" section in MSDN: Control Authoring Overview

Relative Binding in RichTextBox to its Paragraph

I want to display a Line of Text via an ItemsControl beside a RichTextBox. Therefore I created this ControlTemplate:
<RichTextBox Margin="5,0,5,0">
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="5,0,5,0"/>
<Setter Property="LineHeight" Value="30"/>
<Setter Property="LineStackingStrategy" Value="BlockLineHeight"/>
</Style>
</RichTextBox.Resources>
<RichTextBox.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<ItemsControl ItemsSource="{Binding Lines}" Margin="5,0,5,0">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton Content="{Binding}" Height="{Binding BIND_ME_TO_LineHeigh_OF_PARAGRAPH" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<Border Name="Border" CornerRadius="2" Padding="2" Background="White" BorderBrush="Black" BorderThickness="0" >
<ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
</Border>
</StackPanel>
</ControlTemplate>
</RichTextBox.Template>
To make the Items in the ItemsControl the same size as the paragraph's line I want to bind the ToggleButton's height to the LineHeight of the Paragraph which I defined in the Style for the Pararaph ( ). How can I do that?
Thanks

WPF: Groupstyle not working correctly because of Style and/or modified ListBox

I am trying to use a GroupStyle but instead of showing the groupname as a header over the items in the list it only shows the header and not the items.
It works fine until I applied a special style to the list. I then decided this style was pretty bogus so I created a UserControl fro this effect. The problem persists.
The purpose of the UserControl is to have a expending effect on the selected item where normally it could show some info and then more info when expanded.
UserControl:
<UserControl x:Class="MyProject.CustomUC.ExpandingList"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<ListBox x:Name="List"
ItemsSource="{Binding Path=Collection}">
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Border BorderBrush="Blue"
BorderThickness="1"
CornerRadius="2"
Background="White">
<ScrollViewer Focusable="False">
<StackPanel Margin="2" IsItemsHost="True" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ListBox.Template>
<ListBox.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border Margin="4" Name="Border" BorderBrush="Blue" BorderThickness="1" CornerRadius="5" Background="LightBlue">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<ContentPresenter Name="Head"
Margin="4"
Visibility="Visible"
ContentTemplate="{Binding ElementName=List, Path=DataContext.HeadTemplate}"/>
<Border Name="Tail" Visibility="Collapsed" Grid.Row="1" BorderThickness="0,1,0,0" BorderBrush="Blue">
<ContentPresenter Margin="4"
ContentTemplate="{Binding ElementName=List, Path=DataContext.TailTemplate}" />
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Tail" Property="Visibility" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Grid>
</UserControl>
Using the UserControl:
<CustomUC:ExpandingList Collection="{Binding Path=List}">
<CustomUC:ExpandingList.HeadTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DisplayName}" />
</DataTemplate>
</CustomUC:ExpandingList.HeadTemplate>
<CustomUC:ExpandingList.TailTemplate>
<DataTemplate DataType="{x:Type ViewModel:ElementViewModel}">
<TextBlock Text="{Binding Path=SomeOtherProperties}" />
</DataTemplate>
</CustomUC:ExpandingList.TailTemplate>
</CustomUC:ExpandingList>
This works if I change from the ExpandingList UserCotnrol:
<ListView ItemsSource="{Binding Path=List}" >
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=DisplayName}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="True">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
Anyone know what could be wrong?
In the ListBox template, replace:
<StackPanel Margin="2" IsItemsHost="True" />
with
<ItemsPresenter Margin="2" />
The ItemsPresenter class has extra logic for groups, that you lose if you're directly using a panel to display the items.

Resources