I added textblock to treeviewitem.
but treeviewitem.header could not bind to this textblock.
what should I do? I want to add objects on treeview. want to develop a custom treeview.
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19" Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
</Grid>
TO
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid Background="#15232e">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19" Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<TextBlock x:Name="PART_Header" Text="{Binding ??????}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
</Grid>
There are probably other ways around your issue, but to speak to your problem directly, the ContentPresenter is getting the entire object.
So if your view model looked like this:
public class Data
{
public string Name { get; set; }
public List<Data> Children { get; set; }
}
Then basically the ContentPresenter's ContentSource property is basically going to set Content, ContentTemplate, etc.
(See https://learn.microsoft.com/en-us/dotnet/api/system.windows.controls.contentpresenter.contentsource?view=netframework-4.8)
And in your treeviews hierarchical data template might look like this:
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
Where the inner part will basically be the data template given to the presenter, and the ItemsSource will be how children are determined.
So - for your case, you're either going to want to bind Text to data directly in the HierarchicalDataTemplate as noted above, or if you really do want to customize the ControlTemplate of TreeViewItem, you'll can provide the TextBlock as the PART_Header, but with a binding to an element of the tree. Given the Data class above, that would look like this:
<ControlTemplate>
...
<TextBlock x:Name="PART_Header" Text="{Binding Name}"/>
...
</ControlTemplate>
Let me know if that hits your use-case, hard to say without more info unfortunately. Good luck!
Related
I have edited the standard GroupBox template as I wanted to customize it. Apart from other customizations, I wanted the GroupBox header to be Horizontally aligned in the Center instead of Left or Right. The alignment of the Header is not a problem however, the real problem is the OpacityMask defined for the Border controls. The opacity mask sets the transparent space behind the group box header where the borders are not drawn. I haven't able to figure it out how to place the transparent space gap behind the group box header when I set the header to the center.
<ControlTemplate x:Key="GroupBoxControlTemplate1" TargetType="{x:Type GroupBox}">
<Grid SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="6"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="6"/>
</Grid.RowDefinitions>
<Border Background="{TemplateBinding Background}" BorderBrush="Transparent"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4" Grid.Column="1" Grid.ColumnSpan="4"
Grid.Row="1" Grid.RowSpan="3" HorizontalAlignment="Stretch"/>
<Border x:Name="Header" Grid.Column="2" Grid.RowSpan="2" HorizontalAlignment="Left"
Padding="3,1,3,0" VerticalAlignment="Stretch">
<Border.Effect>
<DropShadowEffect BlurRadius="10" Direction="334"/>
</Border.Effect>
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Content="{TemplateBinding Header}"
ContentSource="Header"
ContentStringFormat="{TemplateBinding HeaderStringFormat}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
RecognizesAccessKey="True" Height="Auto"
VerticalAlignment="Center"
HorizontalAlignment="Center"
OpacityMask="#FF3844BD" Margin="0,1,0,0">
</ContentPresenter>
</Border>
<ContentPresenter Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Grid.Column="1" Grid.ColumnSpan="2" Grid.Row="2"/>
<Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="4" Grid.ColumnSpan="3" Grid.Row="1" Grid.RowSpan="3" RenderTransformOrigin="0.5,0.5" Margin="0">
<Border.OpacityMask>
<MultiBinding ConverterParameter="7" UpdateSourceTrigger="Default">
<MultiBinding.Converter>
<BorderGapMaskConverter/>
</MultiBinding.Converter>
<Binding Path="ActualWidth" ElementName="Header"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Border.OpacityMask>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4">
<Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4"/>
</Border>
</Border>
</Grid>
</ControlTemplate>
The header text should be at the center of the GroupBox currently it is on the left side which is the default position of GroupBox.
By link here specify, you need to modify parameter value. But ConverterParameter is not a DependencyProperty, you cannot bind any value to it. I suggest you write your own converter to return VisualBrush to your GroupBox
You can also check source code of BorderGapMaskConverter here
I'm actually overriding the ControlTemplate of the default WPF TextBox and i'd like to add a Title to it. The idea here is that the title will be displayed as a placeholder when the TextBox is empty and not focused, and will slide up at the top to become the title in the other cases.
As the TextBox don't have a PlaceHolder or a Title property, i thought i could bind my title TextBlock to the ToolTip in order to be able to do this:
<TextBox ToolTip="MyTextBoxTitle"/>
My template looks like this :
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="14"/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock x:Name="Title" Text="{Binding Path=ToolTip}" Margin="8,14,0,0" Grid.Row="0" Grid.RowSpan="2" Foreground="{StaticResource TextBox.Static.Border}"></TextBlock>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden" Grid.Row="1"/>
<Rectangle x:Name="UnfocusedUnderLine" Fill="{StaticResource TextBox.Static.Border}" Height="6" Margin="0,1,0,0" Grid.Row="2"/>
<Rectangle x:Name="UnderLine" Fill="{StaticResource TextBox.Focus.Border}" Height="6" Margin="0,1,0,0" Grid.Row="2" Width="0"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
...
</ControlTemplate.Triggers>
</ControlTemplate>
But my Binding on the ToolTip doesn't work, and i can't manage to find a way to make it work, do you know how to do this ?
Use:
Text="{TemplateBinding ToolTip}"
You need a binding whose source is not the DataContext but the templated element which is TextBox in your case.
In tab control i have to add + button to tab item like in screenshot. I added the plus button to tab panel, when i run the program and selecting the tab item the tab control border is not hidden like normal tab control. please check the attached screenshot for clarity of my question.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid
x:Name="templateRoot"
ClipToBounds="true"
KeyboardNavigation.TabNavigation="Local"
SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="ColumnDefinition0" />
<ColumnDefinition x:Name="ColumnDefinition1" Width="0" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition x:Name="RowDefinition0" Height="Auto" />
<RowDefinition x:Name="RowDefinition1" Height="*" />
</Grid.RowDefinitions>
<StackPanel
x:Name="headerPanel"
Grid.Row="0"
Grid.Column="0"
Orientation="Horizontal">
<TabPanel
x:Name="_HeaderPanel"
Panel.ZIndex="1"
IsItemsHost="true"
KeyboardNavigation.TabIndex="1" />
<Button
x:Name="addButton"
Width="50"
Height="30"
Background="LightGray"
BorderBrush="LightGray"
BorderThickness="1,0,0,0"
Command="{Binding ChartAddButton_Click}"
Content="+" />
</StackPanel>
<Border
x:Name="contentPanel"
Grid.Row="1"
Grid.Column="0"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2"
KeyboardNavigation.TabNavigation="Local">
<ContentPresenter
x:Name="PART_SelectedContentHost"
Margin="{TemplateBinding Padding}"
ContentSource="SelectedContent"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
By adding the plus button to tab panel this will occurs. How to fix this. Please give your suggestion.
Please refer the updated screenshot
I assume you're referring to the dotted lines. That's not the border that's being displayed, I think that's the default FocusVisualStyle of the Button.
Try setting,
FocusVisualStyle = "{x:null}"
on the Button.
I just started working with GroupBoxes and I was just wondering why I cant make my corners sharp, as if it was a rectangle.
I've seen a few online and thier corners arent round. Why is that?
<GroupBox x:Name="howTOGroupBox" BorderBrush="White" Foreground="White" Header="How To" HorizontalAlignment="Left" Margin="88,86,0,0" VerticalAlignment="Top" Height="79" Width="221" BorderThickness="1"/>
you can style Your GroupBox ControlTemplate and round to 0 all of the corners:
<Window.Resources>
<Style TargetType="GroupBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0"
BorderThickness="1" BorderBrush="White"
CornerRadius="0,0,0,0">
<ContentPresenter
ContentSource="Header"
RecognizesAccessKey="True" />
</Border>
<Border Grid.Row="1" BorderBrush="White"
BorderThickness="1"
CornerRadius="0,0,0,0">
<ContentPresenter Margin="4" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
I used the recommendation Answer before and modified it a little bit:
<Window.Resources>
<Style TargetType="GroupBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GroupBox">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5px" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Header -->
<Border Grid.Row="1" Grid.Column="0" BorderThickness="1,1,0,0" BorderBrush="Black" CornerRadius="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
<Label Grid.Row="0" Grid.RowSpan="2" Grid.Column="1">
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True" />
</Label>
<Border Grid.Row="1" Grid.Column="2" BorderThickness="0,1,1,0" BorderBrush="Black" CornerRadius="0,0,0,0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
</Grid>
<!-- Content -->
<Border Grid.Row="1" BorderBrush="Black" BorderThickness="1,0,1,1" CornerRadius="0,0,0,0" Padding="10,10,10,10" Margin="0,0,0,0">
<ContentPresenter Margin="4" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
I know I'm very late to the party on this one but... here's a fairly robust, if not rather more complicated than it should be, like a lot of things in WPF, answer.
Firstly, I'm not sure why there isn't a just a CornerRadius property on the GroupBox control itself. It feels like that could have been implemented quite easily.
Secondly, the reason you can't just create a Style that targets the CornerRadius of Border controls in the GroupBox is, when you look at how the framework composes a GroupBox from other controls, the CornerRadius properties of the Border controls it uses are hard set to the value 2. i.e. they can't be overridden by a Style element.
To See how the WPF team originally created the GroupBox control, and to use this as a base for a square-corned GroupBox, right-click on one in the designer and select Edit Template then Edit a Copy.... This will then create a Style which targets GroupBox and overrides its default Template with a copy of exactly how the GroupBox control is normally composed. It will create something like the below. The simplest thing to do next is to go through and change all the CornerRadius elements to 0 and then reference the style as such: <GroupBox Header="Blah" Style="{StaticResource SquareCornerGroupBox}" />
<BorderGapMaskConverter x:Key="BorderGapMaskConverter"/>
<Style x:Key="SquareCornerGroupBox" TargetType="{x:Type GroupBox}">
<Setter Property="BorderBrush" Value="#D5DFE5"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupBox}">
<Grid SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="6"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="6"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="6"/>
</Grid.RowDefinitions>
<Border Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" Grid.Column="0" Grid.ColumnSpan="4" Grid.RowSpan="3" Grid.Row="1"/>
<Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="4" Grid.ColumnSpan="4" Grid.RowSpan="3" Grid.Row="1">
<Border.OpacityMask>
<MultiBinding ConverterParameter="7" Converter="{StaticResource BorderGapMaskConverter}">
<Binding ElementName="Header" Path="ActualWidth"/>
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Self}"/>
<Binding Path="ActualHeight" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Border.OpacityMask>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3">
<Border BorderBrush="White" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2"/>
</Border>
</Border>
<Border x:Name="Header" Grid.Column="1" Padding="3,1,3,0" Grid.RowSpan="2" Grid.Row="0">
<ContentPresenter ContentSource="Header" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ContentPresenter Grid.Column="1" Grid.ColumnSpan="2" Margin="{TemplateBinding Padding}" Grid.Row="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am attempting to modify a TreeView to display the TreeViewItem values above and below their child items, such that:
foo
|bar
||baz
|biz
would become
foo
|bar
||baz
| baz
|bar
|biz
biz
foo
A trimmed representation of the current control template is provided below, provided with no guarantee that this snippet compiles:
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19"
Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ToggleButton x:Name="Expander"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"/>
<Border Name="Bd"
Grid.Column="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"/>
<TextBlock Text="Some Binding Goes Here"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="2"/>
</Grid>
</ControlTemplate>
The repeated entries would not have children, it would just be the display value. Thus far I can modify the TreeView ContainerStyle using a ControlTemplate to insert a TextBlock at the appropriate place in the visual tree. What data binding should be used in order to fetch the appropriate display value?
Why not use a ContentPresenter again?
<ContentPresenter ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Grid.Row="2"
Grid.Column="1"
Grid.ColumnSpan="2"/>