I have the following HeaderTemplate for an Expander:
<Expander.HeaderTemplate>
<DataTemplate>
<Grid Background="#939393">
<Grid.RowDefinitions>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" CornerRadius="5,5,5,5"
Background="Transparent" BorderBrush="#FF000000" Margin="1" BorderThickness="1,1,1,1" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="DarkGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<TextBlock Grid.Column="0" Background="#6E6E6E"/>
<ToggleButton Grid.Column="0" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}}" Focusable="False">
<Image Source="{Binding IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}, Converter={StaticResource boolToExpanderDirectionConverter}}"/>
</ToggleButton>
<TextBlock Grid.Column="1" Text="General" Margin="5,1,1,1" VerticalAlignment="Top" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Expander.HeaderTemplate>
This Headertemplate I have defined directly at one Expander. Now I want to move this Template to a Resource and apply it to all Expanders. My problem now is, that I don't know how to set the Header of the TextBlock in the Template to the Header of the Expander.
I knwo there's a way with TemplateBinding, but unfortunately I don't know how to use this.
TemplateBinding can only be used within a ControlTemplate.TemplateBinding is used for binding to the element properties within the template definition..
here in your example you have used controltemplate for toggleButton.
Example For TemplateBinding
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ContentPresenter TextElement.Foreground="{TemplateBinding Foreground}" x:Name="contentPresenter"/>
</Border>
<ControlTemplate.Triggers>
.....
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<ToggleButton Grid.Column="0" Background="Red" BorderBrush="Black" BorderThickness="1" Foreground="White"/>
Here Border and Contentpresnter will bind properties of ToggleButton that is alreday defined in its defination.
But in your example you used Datatemplate..so you cant use TemplateBinding ..Please Follow This link for Binding Syntax.
Solution For Your example
Using Binding syntax we can bind Header property to different exapnder
Text="{Binding Path=Header,RelativeSource={RelativeSource AncestorType={x:Type Expander}}}"
<Window.Resources>
<DataTemplate x:Key="ExpanderHeaderTemplate">
<Grid Background="#939393">
<Grid.RowDefinitions>
<RowDefinition Height="22"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" CornerRadius="5,5,5,5"
Background="{TemplateBinding Background}" BorderBrush="#FF000000" Margin="1" BorderThickness="1,1,1,1" SnapsToDevicePixels="True">
<ContentPresenter x:Name="contentPresenter"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="DarkGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<TextBlock Grid.Column="0" Background="#6E6E6E"/>
<ToggleButton Grid.Column="0" Background="Red" IsChecked="{Binding IsExpanded, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}}" Focusable="False">
<Image Source="{Binding IsExpanded, RelativeSource={RelativeSource FindAncestor, AncestorType=Expander}, Converter={StaticResource boolToExpanderDirectionConverter}}"/>
</ToggleButton>
<TextBlock Grid.Column="1" Text="{Binding Path=Header,RelativeSource={RelativeSource AncestorType={x:Type Expander}}}" Margin="5,1,1,1" VerticalAlignment="Top" FontWeight="Bold"/>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel>
<Expander Header="General1" HeaderTemplate="{StaticResource ExpanderHeaderTemplate}"/>
<Expander Header="General2" HeaderTemplate="{StaticResource ExpanderHeaderTemplate}"/>
</StackPanel>
you can have a idea of Template binding by below code i had implemented this when i was learning XAML.
<Button Template="{DynamicResource CircleButton}" Background="Green" Content="1"></Button>
<ControlTemplate x:Key="CircleButton" TargetType="{x:Type Button}">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" MinHeight="36" MinWidth="36">
<Ellipse Fill="{TemplateBinding Background}"></Ellipse>
<ContentPresenter TextBlock.FontFamily="Calibri" TextBlock.FontSize="24" TextBlock.Foreground="Wheat" HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
you have to give a x:Key to control Template and when you are binding it with some specific element define that x:key there like i did Template="{DynamicResource CircleButton}".
following is your case:
<Style TargetType="{x:Type Expander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
// Do your thing.
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
this will apply to all Expander throught your application. You can put this Style into App.xaml file for code cleanness. hope this'll help you.
Since you are specifying a HeaderTemplate via a DataTemplate, the DataContext of the template IS the Header. This simple example works:
<Expander Header="Test">
<Expander.HeaderTemplate>
<TextBlock Text="{Binding}"/>
</Expander.HeaderTemplate>
</Expander>
Related
I have the code for the TabControl below. I want to achieve tab style similar to google chrome browser.
I want to make the bottom corners slightly rounder towards the pinkish background and not inwards.
How to set the rounded corners of TabItem to achieve the same effect as Google?
The resulting graph I have now:
Xmal:
<Window.Resources>
<SolidColorBrush x:Key="PrimaryBG" Color="#ad00ad"/>
<SolidColorBrush x:Key="Blueish" Color="#5252ff"/>
<SolidColorBrush x:Key="Greenish" Color="#005757"/>
<SolidColorBrush x:Key="Blackish" Color="#2e2e00"/>
<Style x:Key="{x:Type TabControl}" TargetType="{x:Type TabControl}">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border BorderThickness="0,0,1,1" BorderBrush="#D0CEBF" Grid.Row="1">
<Border BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter ContentSource="SelectedContent"/>
</Border>
</Border>
</Border>
<TabPanel Grid.Row="0" IsItemsHost="true" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TabItem">
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<!--In order to click on the blank part of the TabItem can be successfully selected-->
<Border Background="Transparent" >
<Grid>
<Grid x:Name="g">
<Border CornerRadius="5,5,7,7" Background="{TemplateBinding Background}" Margin="0,0,0,-1"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"/>
</Grid>
<Border BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</Grid>
</Border>
<!--Add ControlTemplate.Triggers to change the background color of the selected TabItem.-->
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="{DynamicResource PrimaryBG}" Name="grid" >
<TabControl HorizontalAlignment="Center" HorizontalContentAlignment="Stretch" Margin="0,0,0,0"
Name="tabControl1" VerticalAlignment="Top" >
<TabItem Header="Dashboard" Name="tabItem1" Background="{DynamicResource Blueish}" Foreground="White"
HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Width="180" HorizontalAlignment="Center"
FontFamily="Leelawadee UI" FontSize="20" Margin="0,0,0,0" Padding="0,0,0,0">
<Border Background="#5252ff" Margin="0,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid, Path=ActualHeight}">
<StackPanel>
<TextBox Width="200" Height="25"/>
<TextBox Width="200" Height="25"/>
</StackPanel>
</Border>
</TabItem>
<TabItem Header="Invoicing" Name="tabItem2" Background="{DynamicResource Greenish}" Foreground="White"
HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Width="180" HorizontalAlignment="Center"
FontFamily="Leelawadee UI" FontSize="20" Margin="0,0,0,0" Padding="0,0,0,0">
<Border Background="#005757" Margin="0,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid, Path=ActualHeight}" >
<Button Width="80" Height="25"/>
</Border>
</TabItem>
<TabItem Header="Transactions" Name="tabItem3" Background="{DynamicResource Blackish}" Foreground="White"
HorizontalContentAlignment="Center" VerticalAlignment="Stretch" Width="180" HorizontalAlignment="Center"
FontFamily="Leelawadee UI" FontSize="20" Margin="0,0,0,0" Padding="0,0,0,0" >
<Border Background="#2e2e00" Margin="0,0,0,0" Padding="0,0,0,0" HorizontalAlignment="Center" VerticalAlignment="Stretch" Width="{Binding ElementName=grid,Path=ActualWidth}" Height="{Binding ElementName=grid, Path=ActualHeight}" >
<ComboBox Width="300" Height="25"/>
</Border>
</TabItem>
</TabControl>
</Grid>
Edit:
Is it possible to give a path of the red line in the figure?
You can create any shape by Path and place it both sides of tab. For example, such Path would be as follows.
<Path Width="20" Height="40" Stretch="Uniform" Fill="Blue"
StrokeThickness="2" Stroke="Red"
Data="M 20,40 L 0,40 0,40 C 4,40 10,36 10,30 L 10,10 C 10,0 16,0 20,0"/>
You can flip it by <ScaleTransform ScaleX="-1"/>.
Edit:
Edited Path. You can draw outline by Stroke and leave a segment open by removing Z.
I need to display all the tab headers in a dropdownlist.I have implemented the tab and added the down arrow button to it. I added a popup to list the items along with the button. But i cannot find a way to bind the header of the tab items to the list in the pop (Name = PresetPopup). I have tried binding the itemsource of "ConnectionList". But the ConnectionList is not recogonized in the ConnectionPages.xaml.cs file. Any code how to bind this will be helpful. Or any other way to do this?
<Style TargetType="{x:Type TabControl}">
<Setter Property="Padding" Value="2"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid x:Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<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 Orientation="Horizontal" Grid.Column="0">
<TabPanel x:Name="headerPanel" Background="Transparent" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
<Border Height="30" VerticalAlignment="Center" BorderBrush="LightGray" BorderThickness="1">
<Grid>
<materialDesign:PackIcon Kind="ArrowDropDown" VerticalAlignment="Center" Width="15" />
<ToggleButton Name="OpenPopupButton" Background="Transparent" BorderBrush="Transparent" VerticalAlignment="Center">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="BorderThickness" Value="0"/>
</Style>
</ToggleButton.Style>
<materialDesign:PackIcon Background="White" Foreground="Black" Kind="ArrowDropDown" Height="15" VerticalAlignment="Center" Width="15" />
</ToggleButton>
<Popup Name="PresetPopup" IsOpen="{Binding ElementName=OpenPopupButton, Path=IsChecked}" PlacementTarget="{Binding ElementName=OpenPopupButton}" AllowsTransparency="True" PopupAnimation="Slide" StaysOpen="False" >
<ListBox Name="ConnectionList" ItemsSource="{Binding ConnectionsTab}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="a"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Popup>
</Grid>
</Border>
</StackPanel>
<Border x:Name="contentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
<ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
...........
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Actually my final output requirement is similiar to this
final output
I would like to show a popup to help the users to add a new row to a datagrid, by adding a button in the last row of the datagrid. I figured there must be some sort of DataGridTemplateColumnproperty I have to set for the newrow/addrow template?
What you can do is to write a style for "DataGridRow" as
Thi is the working example
<Style x:Type="DataGridRow">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" />
<Button Visibility = "{Binding IsLastRow}"/>!--can set converter to convert boolean to visibilty as well.
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So the binded property basically check the logic of the last row.(I am not sure wpf datagrid by itself provides some kind of property like "IsLastRow" or not. But if not anytime you can write your own logic).
In ContentTemplate you can define your button handler or command object.
You could use a DataGridRow style with a data trigger that changes the template of the last row:
<DataGrid x:Name="dgrid">
<DataGrid.Resources>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding}" Value="{x:Static CollectionView.NewItemPlaceholder}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Visibility="{TemplateBinding DetailsVisibility}"/>
<DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
</SelectiveScrollingGrid>
<Button Content="Add New" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.Resources>
</DataGrid>
Or - if you want to put the Button in a specific column - you could use a DataGridTemplateColumn with a CellTemplate that uses a similar data trigger:
<DataGrid x:Name="dgrid">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Grid>
<TextBlock>...</TextBlock>
<Button x:Name="btn" Content="Add" Visibility="Collapsed" />
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=DataGridRow}}"
Value="{x:Static CollectionView.NewItemPlaceholder}">
<Setter TargetName="btn" Property="Visibility" Value="Visible" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
In my application, I need to make the combobox that I am using have rounded corners. I started with the XAML posted in the answer to this question and have made some modifications. I decided I didn't like the way that one looked as much, so I tried to style it and make it look a bit more like the default combobox. Now my combobox looks like this: ,
and when dropped down:
The issue is that when the user places their mouse over the combobox, it looks like this: . If I use Snoop, I can see this info:
It says
that the value of that border background is being set to "#FFBEE6FD", which is the color that shows when the mouse is over the combobox. The value source is "ParentTemplateTrigger". My issue is that I don't know where this border is coming from or why it's getting that value. I have tried to add template triggers with setters to set the background to white, but I don't know where to set the value for this mysterious border.
Here is the XAML for my ComboBox:
<ComboBox x:Name="ScanSizesComboBox"
Style="{StaticResource roundedCornersComboBox}"
Grid.ZIndex="4"
ItemsSource="{Binding ScanSizes}"
SelectedItem="{Binding SelectedScanSize, Mode=TwoWay}"
ToolTip="{Binding (Validation.Errors)[0].ErrorContent}"
Margin="0,10,89,0"
HorizontalAlignment="Right"
Width="61"
Height="26"
VerticalAlignment="Top"
Grid.Row="4">
</ComboBox>
And here is the style:
<Style x:Key="ComboBoxTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border Name="ComboBoxTextBoxStyleBorder" CornerRadius="2"
BorderThickness="0,1,0,1"
Margin="0,0,1,1"
Background="{TemplateBinding Background}">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsReadOnly" Value="True"/>
</Style>
<!--Rounded corners combo box-->
<Style TargetType="{x:Type ComboBox}" x:Key="roundedCornersComboBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Border Name="roundedCornerComboBoxBorder" BorderBrush="#CCCCCC" BorderThickness="1" CornerRadius="3" ClipToBounds="True" Background="White">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="White"/>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Canvas>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBox Name="PART_EditableTextBox"
Panel.ZIndex="0"
Style="{StaticResource ComboBoxTextBoxStyle}"
Padding="0,0,0,0"
IsHitTestVisible="False"
Height="{TemplateBinding Height}">
</TextBox>
<ToggleButton Grid.Column="1" Margin="0, 0, 0, 0"
Panel.ZIndex="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Transparent"
Background="Transparent"
Height="{TemplateBinding Height}"
Width="60"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
HorizontalContentAlignment="Right"
ClickMode="Press">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="true">
<Setter Property="Background"
Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
<Path Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"
Fill="DodgerBlue" />
</ToggleButton>
<ContentPresenter Name="ContentSite"
Cursor="Arrow"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="3,0,0,0">
</ContentPresenter>
<Popup Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Grid Name="DropDown"
SnapsToDevicePixels="True"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border
x:Name="DropDownBorder"
BorderThickness="1"
CornerRadius="5"
Background="White"
BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</Canvas>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Ultimately, I would like for the user to be able to place his/her mouse over the combobox, and have it just look the same as it does when it is not highlighted. Any help is appreciated. Thanks.
Continuing from our comments conversation (which generally SO tries to avoid so much noise) this may get on you track.
So if I grab just all the template stuff to a bare bones basic default ComboBox and ComboBoxItem from a fresh WPF app, this is the output. Granted you won't need all of it, but it should ensure to an extent all expected functionality and DOM parts are here for reference so you have all the stuff like Triggers, Template Binding pieces etc, all available.
Notice the various Border and Rectangle elements in the various parts that would need to be altered in order to achieve the rounding of everything. I can't however provide any insight into how it would effect anything with MahApps as my experience with that is pretty limited since I've always just made my own stuff to accomplish what it essentially does.
Hope it helps. It's too long for SO's submission requirements though so here's the PasteBin link.
<Style x:Key="ComboBoxTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Border CornerRadius="5,0,0,5"
BorderThickness="1"
Background="{TemplateBinding Background}"
BorderBrush="Black">
<ScrollViewer x:Name="PART_ContentHost"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition MaxWidth="18"/>
</Grid.ColumnDefinitions>
<TextBox Name="PART_EditableTextBox"
Style="{StaticResource ComboBoxTextBoxStyle}"
Padding="5,0,0,0"
Height="{TemplateBinding Height}"/>
<ToggleButton Grid.Column="1" Margin="0"
Height="{TemplateBinding Height}"
Style="{StaticResource ComboBoxButtonStyle}"
Focusable="False"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press">
<Path Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="M 0 0 L 4 4 L 8 0 Z"
Fill="DodgerBlue" />
</ToggleButton>
<ContentPresenter Name="ContentSite"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="5,0,0,0"/>
<Popup Name="Popup"
Placement="Bottom"
IsOpen="{TemplateBinding IsDropDownOpen}"
AllowsTransparency="True"
Focusable="False"
PopupAnimation="Slide">
<Grid Name="DropDown"
SnapsToDevicePixels="True"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border
x:Name="DropDownBorder"
BorderThickness="1"
CornerRadius="5"
Background="Azure"
BorderBrush="Black"/>
<ScrollViewer Margin="4,6,4,6" SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
</Grid>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I'm using WPF 4.0 to develop windows and want to reuse a ControlTemplate in my Resources for various Label controls.
I define a generic base Label Style with the ControlTemplate and then define derived Label Styles to control colors and label text.
I then apply these styles to data triggers based on a property value.
What I have tried so far throws an IllegalArgument exception: 'Style object is not allowed to affect the Style property of the object to which it applies'.
Is there a valid way to do this?
This is what I have so far that produces the exception:
<Style x:Key="BaseLabelStyle" TargetType="{x:Type Label}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="AvailableLabelStyle" TargetType="{x:Type Label}" BasedOn="{StaticResource BaseLabelStyle}">
<Style.Resources>
<Style>
<Setter Property="Label.Background" Value="#FF567E4A"/>
<Setter Property="Label.Foreground" Value="White"/>
<Setter Property="TextBlock.Text" Value="Available"/>
</Style>
</Style.Resources>
</Style>
I want to expand the derived styles to define other color and label text changes.
This derived Style is applied here:
<Label x:Name="Avail_Out_LBL"
HorizontalAlignment="Left" Margin="111,44,0,0"
VerticalAlignment="Top" Width="124" Height="18"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center" SnapsToDevicePixels="False"
Grid.Column="1" Padding="0">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Style.Triggers>
<DataTrigger Binding="{Binding MonitorAndControlData.Availability}" Value="Available">
<Setter Property="Style" Value="{StaticResource AvailableLabelStyle}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
The exception points to the closing /DataTrigger in the Label. I can't tell if the problem is in the Style's use or in the definition up top in the Resources.
Any help would be greatly appreciated.
The problem is that you are trying to change the style from the style, which is not permitted.
What I would do in your situation is create a custom UserControl for your label, which would look like this :
<UserControl ...>
<UserControl.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="24"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
Foreground="{TemplateBinding Foreground}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"/>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Availability, RelativeSource={RelativeSource AncestorType={x:Type theTypeOfYourControl}}}" Value="Available">
<Setter Property="Label.Background" Value="#FF567E4A"/>
<Setter Property="Label.Foreground" Value="White"/>
<Setter Property="TextBlock.Text" Value="Available"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Label x:Name="Avail_Out_LBL"
HorizontalAlignment="Left" Margin="111,44,0,0"
VerticalAlignment="Top" Width="124" Height="18"
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center" SnapsToDevicePixels="False"
Grid.Column="1" Padding="0"/>
</UserControl>
The setters in the trigger are probably not good, you'll have to target the right property to make it work. Also, you will need to make a dependency property named Availability or any other relevant name (I just used the name in your binding) to expose it outside the UserControl. You will need to bind to this DependencyProperty when using your UserControl.
Here are some links on how to do it, with more détails :
http://www.codeproject.com/Articles/32825/How-to-Creating-a-WPF-User-Control-using-it-in-a-W
http://www.wpftutorial.net/dependencyproperties.html