I want to add a TextBox after the last item of a ListView (or at the bottom inside of the ItemsPresenter of a ListView).
At the moment I am defining a template for the last ListViewItem and I am using a converter to be sure which element is the last one.
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource LastItemInContainerConverter}}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<StackPanel Orientation="Vertical">
<Border Name="Border" BorderBrush="#DCDCDC" Background="#eeeeec" BorderThickness="1" Margin="0,0,0,5">
<ContentPresenter />
</Border>
<TextBox>Hello!</TextBox>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
But the items are in a ObservableCollection and I am getting problems about the layout refreshing upon adding and removing items.
Any approach or idea how can I define that?
Ok, I find the solution.
<ListView.Template>
<ControlTemplate>
<Border>
<ScrollViewer>
<!-- this is needed -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<ItemsPresenter />
<TextBlock Grid.Row="1">Hello!!!</TextBlock>
</Grid>
</ScrollViewer>
</Border>
</ControlTemplate>
</ListView.Template>
Related
I want to add a button above all column in Charts in the Silverlight Toolkit.
Same with this Picture:
I add style for DataPointStyle:
<Style x:Key="ColorByGradeColumn" TargetType="toolkit:ColumnDataPoint">
<Setter Property="Background" Value="DarkGray"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:ColumnDataPoint">
<Border
MouseEnter="Border_MouseEnter"
MouseLeave="Border_MouseLeave"
Background="{Binding Legend.Color,
Converter={StaticResource stringToSolidColorBrushConverter}}"
BorderThickness="0.5"
Tag="{Binding Legend}"
MouseLeftButtonUp="Col_MouseLeftButtonUp">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
but i don't know where i should add button.
You can add anything you need to the ControlTemplate.
In your case this would mean you have to add a Panel (e.g. a Grid) to arrange the button and the bar:
<ControlTemplate TargetType="toolkit:ColumnDataPoint">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="0" ... />
<Border Grid.Row="1" ... />
</Grid>
</ControlTemplate>
I am creating a WPF custom control that inherits from ItemsControl. In the ControlTemplate of my control I have an ItemsPresenter. The problem is that I need to be able to get content in the items presenter to fill the entire content area. In the code below I have a simplified example of the broken code and also what I am trying to accomplish. BTW setting HorizontalAlignment and VerticalAlignment to Stretch causes the content expand horizontally but not vertically.
<Window x:Class="yada"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768" Width="1024">
<Grid>
<Grid.Resources>
<Style TargetType="Border" x:Key="stepBorder">
<Setter Property="Background" Value="CadetBlue"></Setter>
<Setter Property="BorderBrush" Value="Green" ></Setter>
<Setter Property="BorderThickness" Value="2"></Setter>
<Setter Property="Padding" Value="25"></Setter>
</Style>
</Grid.Resources>
<TabControl Margin="0,20,0,0">
<TabItem Header="Broken">
<Border>
<ItemsControl>
<ItemsControl.Items>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}">
<TextBlock Text="Border fills small region near the top"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</ItemsControl.Items>
</ItemsControl>
</Border>
</TabItem>
<TabItem Header="Works">
<Border>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}" >
<TextBlock Text="Border fills entire control"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</Border>
</TabItem>
</TabControl>
</Grid>
</Window>
Here is some code from my control. I cant include it all, there is too much. I think this is the relevant part however:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Wizard}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" x:Name="ContentRow" />
<RowDefinition Height="{Binding ElementName= NavButtonPanel,Path=ActualHeight}"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" x:Name="ContentScrollViewer" MaxHeight="{Binding ElementName=ContentRowHeight, Path=ActualHeight}">
<ItemsPresenter
x:Name="Presenter"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
</ItemsPresenter>
</ScrollViewer>
<Border Style="{TemplateBinding NavButtonPanelStyle}" Grid.Row="1" x:Name="NavButtonPanel">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
</StackPanel>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate></DataTemplate>
</Setter.Value>
</Setter>
As usual, just posting on SO gets me halfway to my answer.
It turns out the ItemsControl is using an evil stackpanel as a container for items. Fortunately there is a top-secret property called ItemsPanel that lets you change this. Just set it to a grid as shown below and you are in business.
In my case I am writing a custom control that inherits from ItemsControl so in the Style I add this property setter:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid></Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
I have the following style:
<Style TargetType="{x:Type local:MetroTabControl}">
<Style.Triggers>
<Trigger Property="SingleRow" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MetroTabControl}">
<Grid>
<Grid KeyboardNavigation.TabNavigation="Local" SnapsToDevicePixels="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid>
<ScrollViewer x:Name="ScrollViewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Hidden" Style="{DynamicResource TabPanelScrollViewer}">
<TabPanel x:Name="HeaderPanel" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>
</ScrollViewer>
<Button x:Name="AddTabItem" Content="" Style="{DynamicResource TabControlButton}" HorizontalAlignment="Right" VerticalAlignment="Top"/>
</Grid>
<Border Grid.Row="1" x:Name="TabPanelBorder" Background="Transparent">
<Rectangle x:Name="TabPanelBorderRectangle" Fill="{StaticResource TabPanelBorderBrush}" Height="2"/>
</Border>
<Border Grid.Row="2" Background="{StaticResource TabControlBackground}"/>
<ContentPresenter Grid.Row="2" Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--<Setter Property="Template" Value="{StaticResource MetroTabControlSingleRow}" />-->
</Trigger>
<Trigger Property="SingleRow" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MetroTabControl}">
<Grid KeyboardNavigation.TabNavigation="Local" SnapsToDevicePixels="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Background="Transparent" BorderThickness="0,0,0,2" BorderBrush="{StaticResource TabPanelBorderBrush}">
<DockPanel LastChildFill="True">
<Button x:Name="AddTabItem" Style="{DynamicResource TabControlButton}" DockPanel.Dock="Right">
<Path Stroke="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}" Data="M0,4 H8 M4,0 V8" StrokeThickness="2" />
</Button>
<TabPanel x:Name="HeaderPanel" IsItemsHost="True" Panel.ZIndex="1" KeyboardNavigation.TabIndex="1"/>
</DockPanel>
</Border>
<Border Grid.Row="1" Background="{StaticResource TabControlBackground}"/>
<ContentPresenter Grid.Row="1" Name="PART_SelectedContentHost" ContentSource="SelectedContent"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--<Setter Property="Template" Value="{StaticResource MetroTabControlMultiRows}" />-->
</Trigger>
</Style.Triggers>
</Style>
I want to have another style, BasedOn the above, but with one change - I want to change the Fill Color of the TabPanelBorderRectangle Rectangle.
So, to use the BasedOn I wrote the following:
<Style TargetType="{x:Type local:MetroTabControl}" BasedOn="{StaticResource {x:Type local:MetroTabControl}}">
</Style>
But I have no Idea how to change the color of the TabPanelBorderRectangle Rectangle from the BasedOn Style.
I tried something like
<Setter TargetName="TabPanelBorderRectangle" Property="Fill" Value="Red"/>
but it doesnt work (TargetName property cannot be set on a Style Setter)
..
How can I do this?
As error states you cannot use TargetName in style setters.
As a workaround what you can do is, instead of using StaticResource for your brush, bind it using DynamicResource so that we can take advantage of resource look up behaviour of XAML.
<Rectangle x:Name="TabPanelBorderRectangle"
Fill="{DynamicResource TabPanelBorderBrush}"/>
Now, in your style you can override that brush by specifying the same key for a brush and provide your color value there.
<Style TargetType="{x:Type local:MetroTabControl}"
BasedOn="{StaticResource {x:Type local:MetroTabControl}}">
<Style.Resources>
<SolidColorBrush x:Key="TabPanelBorderBrush" Color="Green"/>
</Style.Resources>
</Style>
Since the brush is binded via dynamic resource it will pick the most local value from your style resource which will be Green in above case.
I have ObservableCollection with items which I want to display in a ListBox.
Also I write a template for ListboxItem for correct display of my collection.
On this stage everything works fine.
in .cs
Sensors = new ObservableCollection<Sensor>();
...
lstBox.ItemsSource = Sensors;
in .xaml
...
<DataTemplate x:Key="SensorTileTemplate">
<Border>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}" Grid.Row="0" Grid.ColumnSpan="3"></TextBlock>
<Image Source="{Binding ImageModel.ImgSource}" Style="{StaticResource ImageGlowStyle}" Height="72" Grid.Row="1" Grid.Column="0"></Image>
<StackPanel Grid.Row="1" Grid.Column="1" Margin="5">
<TextBlock Text="IP:"></TextBlock>
<TextBlock Text="Port:"></TextBlock>
<TextBlock Text="Command port:"></TextBlock>
</StackPanel>
<StackPanel Grid.Row="1" Grid.Column="2" Margin="5">
<TextBlock Text="{Binding DeviceAddress}"></TextBlock>
<TextBlock Text="{Binding DeviceDataPort}"></TextBlock>
<TextBlock Text="{Binding DeviceControlPort}"></TextBlock>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
<Style x:Key="ContainerStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="ListBoxItem.Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
...
<ListBox Name="lstBox" Focusable="False"
SelectionChanged="lstBox_SelectionChanged"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource SensorTileTemplate}"
ItemContainerStyle="{StaticResource ContainerStyle}">
</ListBox>
The problem appears when I need to group certain items using expander as a group container.
in .cs
...
ICollectionView view = CollectionViewSource.GetDefaultView(Sensors);
view.GroupDescriptions.Add(new PropertyGroupDescription("GroupNumber"));
lstBox.ItemsSource = view;
...
in .xaml
<!--Same Template and Style-->
...
...
<Style x:Key="GroupContainerStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Group #" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
...
<ListBox Name="lstBox" Focusable="False"
SelectionChanged="lstBox_SelectionChanged"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource SensorTileTemplate}"
ItemContainerStyle="{StaticResource ContainerStyle}">
<ListBox.GroupStyle>
<GroupStyle ContainerStyle="{StaticResource GroupContainerStyle}" />
</ListBox.GroupStyle>
</ListBox>
This code works and groups items but items become invisible.
So without grouping items display correctly but with grouping expanders show nothing in it.
I think there is something about ItemsPresenter in Expander but can't figure out what.
The problem was in one third party theme I use in my app. That theme has a ListBox template like:
<Style TargetType="{x:Type ListBox}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBox}">
<Grid>
<Border x:Name="Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="2" Background="{DynamicResource ControlBackgroundBrush}" />
<ScrollViewer Margin="1" Style="{DynamicResource NuclearScrollViewer}" Focusable="false" Background="{x:Null}">
<StackPanel Margin="1,1,1,1" IsItemsHost="true" />
</ScrollViewer>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" Value="{DynamicResource DisabledBackgroundBrush}" TargetName="Border" />
<Setter Property="BorderBrush" Value="{DynamicResource DisabledBorderBrush}" TargetName="Border" />
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So I use an ItemsPresenter instead of the StackPanel in that template and everything works now.
How can I get HCC using a tab control to "Stretch" all the way down vertically? How can I achieve this?
Here is the header content control XAML:
<HeaderedContentControl
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}" />
Here is the corresponding style info:
<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel>
<Button
Command="{Binding Path=CloseCommand}"
Content="X"
Cursor="Hand"
DockPanel.Dock="Right"
Focusable="False"
FontFamily="Arial"
FontSize="9"
FontWeight="Bold"
Margin="0,1,0,0"
Padding="0"
VerticalContentAlignment="Bottom"
Width="16" Height="16"
/>
<ContentPresenter
Content="{Binding Path=DisplayName}"
/>
</DockPanel>
If you examine the control template for the HeaderedContentControl you'll find it puts the content in a StackPanel which is why content isn't stretching vertically. This is the default template:
<Style x:Key="HeaderedContentControlStyle"
TargetType="{x:Type HeaderedContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type HeaderedContentControl}">
<StackPanel>
<ContentPresenter ContentSource="Header"/>
<ContentPresenter/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So if we replace the StackPanel with a Grid like this:
<Style x:Key="HeaderedContentControlStyle"
TargetType="{x:Type HeaderedContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type HeaderedContentControl}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentPresenter ContentSource="Header"/>
<ContentPresenter Grid.Row="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and use that style
<HeaderedContentControl
Style="{StaticResource HeaderedContentControlStyle}"
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}" />
then the content should stretch vertically.