I am using WPF datagrid. Using the following style I am applying checkbox to one of the columheader.
<Style x:Key="TestDataColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<CheckBox x:Name="chkbxCheckAll" VerticalAlignment="Center" HorizontalAlignment="Center" IsChecked="{Binding Path=CheckAll, Mode=TwoWay, ElementName=TestDataScreen}" Click="chkbxCheckAll_Click">
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Control.Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="1" Color="#FFC2E3F6" />
<GradientStop Offset="0.53" Color="#FFF1FBFD" />
<GradientStop Color="#FFF2FAFD" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Control.BorderBrush" Value="#FFDADADA" />
<Setter Property="Control.BorderThickness" Value="1,0,1,1" />
<Setter Property="Control.Height" Value="26" />
<Setter Property="Control.HorizontalContentAlignment" Value="Center"/>
</Style>
The problem I am facing is, I can see the checkbox in columnheader but columnheader background color is not changed.
Try adding a border around the checkbox like this
<Border Background="{TemplateBinding Background}">
<CheckBox x:Name="chkbxCheckAll" VerticalAlignment="Center"
HorizontalAlignment="Center"
IsChecked="{Binding Path=CheckAll, Mode=TwoWay, ElementName=TestDataScreen}"
Click="chkbxCheckAll_Click">
</CheckBox>
</Border>
Edit:
If you make the background black and set the background of the CheckBox to TemplateBinding Background you will notice that a littlebit of the checkbox is getting black. This has to do with the build-in style of the CheckBox.
Just a guess, maybe Background was originally bounded to something in the default Template which you override.
Maybe you can try fixing that by adding a TemplateBinding for Background on the CheckBox:
<CheckBox x:Name="chkbxCheckAll" ... Background="{TemplateBinding Background}">
By the way, this is untested.
Related
I'm using Prism for UI composition and would need a way to switch the active view by a RadioButton. I want a group of RadioButtons that would change the desired view when checked. I thought the TabControl would be perfect for this. I thought I could just use a style to change the template of the TabItem to a RadioButton, but it is not switching tabs with the RadioButton is selected. Here's the template I have for the TabItem
<ControlTemplate TargetType="{x:Type TabItem}">
<RadioButton IsChecked="{TemplateBinding IsSelected}"
Content="{TemplateBinding Header}" />
</ControlTemplate>
I thought that should make the tab selected when the RadioButton is checked, but that doesn't appear to happen. What am I doing wrong or is there another way to achieve the same result?
Also is there a way to make the first view of the TabControl active? I tried SelectedIndex="0" on the tab control, but that doesn't seem to set the IActiveAware.IsActive on the view.
Here is the exact code that I'm using for styling the TabControl and TabItem
<Style TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Foreground" Value="{StaticResource mainRegionControlForegroundBrush}"></Setter>
<Setter Property="Header" Value="{Binding Content.DataContext.Title, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<RadioButton IsChecked="{TemplateBinding IsSelected}" Content="{TemplateBinding Header}" Foreground="{TemplateBinding Foreground}" Margin="{TemplateBinding Margin}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TabControl}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid KeyboardNavigation.TabNavigation="Local" ClipToBounds="True" SnapsToDevicePixels="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel IsItemsHost="True" Orientation="Horizontal" Margin="10,0"/>
<ContentPresenter Grid.Row="1" Name="PART_SelectedContentHost" Content="{TemplateBinding TabControl.SelectedContent}" ContentSource="SelectedContent" ContentTemplate="{TemplateBinding TabControl.SelectedContentTemplate}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I figured it out. TemplateBinding wasn't updating the parent property, so IsSelected was never set on the TabItem. I changed the binding to
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
and it worked.
You simply need to define a new ControlTemplate for the RadioButton that uses a Border element:
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<ControlTemplate x:Key="TabTemplate" TargetType="{x:Type RadioButton}">
<Border BorderBrush="Black" Background="{TemplateBinding Background}"
BorderThickness="1,1,1,0" CornerRadius="5,5,0,0" Padding="5">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template" Value="{StaticResource TabTemplate}" />
<Setter Property="Height" Value="26" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="LightGray" />
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<RadioButton Content="Tab 1" />
<RadioButton Content="Tab 2" />
<RadioButton Content="Tab 3" />
</StackPanel>
I also added a basic Trigger so that you can see how to Style the selected item differently from the other tabs.
UPDATE >>>
Sorry, I clearly didn't read your question properly. To do it the other way around, it's a lot more work and unfortunately, you are going to have to do your bit because there is just too much code. So to start with, your example code didn't work because you were trying to define a new ControlTemplate for the TabControl, whereas you actually just need to define one for the TabItem.
The first step to do this is to actually define a new ControlTemplate for the whole TabControl which includes the ControlTemplate for the TabItem. Your example didn't work because you failed to replicate a lot of parts of the default ControlTemplate, so we need to do that. How? Well we can find the default ControlTemplate in the TabControl Styles and Templates page on MSDN.
So after looking at that, you'll understand why I can't put all that code here. At first, you basically need to use that exact XAML to reproduce the default ControlTemplate... when it is all working as normal, then you can start to tweak it to your requirements. If you look down the linked page, you'll see this:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
...
This is where the default ControlTemplate for the TabItem starts. Looking further down, underneath the VisualStateManager.VisualStateGroups, you should see this:
<Border x:Name="Border"
Margin="0,0,-4,0"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<Border.BorderBrush>
<SolidColorBrush Color="{DynamicResource BorderMediumColor}" />
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="{DynamicResource ControlLightColor}"
Offset="0.0" />
<GradientStop Color="{DynamicResource ControlMediumColor}"
Offset="1.0" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Border.Background>
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"
RecognizesAccessKey="True" />
</Border>
This is what defines what a TabItem should look like and is where you need to add your RadioButton (instead of this Border and it's contents). You'll probably also need to remove or adjust anything that references the old controls, eg. in the VisualStateManager.VisualStateGroups section.
I have a ToggleButton in my window and styled in my ResourceDictionary. The reason why it's in the ResourceDictionary is because I have several or more ToggleButton soon which has to have the same look.
<Style x:Key="Standardbutton" TargetType="{x:Type ToggleButton}">
<Setter Property="FontSize" Value="18" />
<Setter Property="Foreground" Value="White" />
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources/Standard_Button_Normal.png" />
</Setter.Value>
</Setter>
<Setter Property="Height" Value="56" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Name="border" BorderThickness="0" Padding="0,0" BorderBrush="DarkGray" CornerRadius="0" Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center" Name="content" Margin="15,0,0,0"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background">
<Setter.Value>
<ImageBrush ImageSource="Resources/Standard_Button_Pressed.png" />
</Setter.Value>
</Setter>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFF9CE7B" Offset="0"/>
<GradientStop Color="#FFE88C41" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Now this ToggleButton style has a default background and also when "IsChecked" is true, it will have different background (as you can see on my XAML code above).
Now these toggle buttons has to have icon + text combined, like what I did here (sorry for my lame XAML code)
<ToggleButton Style="{DynamicResource Standardbutton}" Margin="0,0,0,4">
<StackPanel Orientation="Horizontal">
<Image Source="Resources/scan_26x26.png" />
<TextBlock Text="Scan"/>
</StackPanel>
</ToggleButton>
The question is, how can I have a different icon when the ToggleButton is checked (IsChecked=True)?
Here are some images that might help you to understand the question
Normal ToggleButton Style
IsChecked=True Style
My design goal is to have a different icon when IsChecked=True
Add both images to the control template, and bind their Visibility property to the IsChecked property (use an IValueConverter to convert from true/false to the appropriate Visibility enum value).
<ToggleButton Style="{DynamicResource Standardbutton}" Margin="0,0,0,4">
<StackPanel Orientation="Horizontal">
<Image Source="Resources/scan_26x26.png"
Visibility="{Binding
RelativeSource={RelativeSource AncestorType=ToggleButton},
Path=IsChecked,
Converter={StaticResource BoolToVisibleConverter}}" />
<Image Source="Resources/anotherimage.png"
Visibility="{Binding
RelativeSource={RelativeSource AncestorType=ToggleButton},
Path=IsChecked,
Converter={StaticResource BoolToCollapsedConverter}}" />
<TextBlock Text="Scan"/>
</StackPanel>
</ToggleButton>
I used two converters BoolToVisibleConverter and BoolToCollapsedConverter, but you could also use a ConverterParameter to accomplish the same thing.
I have few buttons as Menu in my WPF App.
This scenario is something like menu in a website.
When I click one of the button, I want that button style to be different from others, and when I select another, the previous one should be normal and a selectedstyle should apply on this selected button.
Can you tell me how can I achieve this through ControlTemplate or do I have to maintain a IsSelected property that let us know which button is selected?
Thanks,
VJ
You can try with the RadionButton. The below sample will create a Flat button look for the RadioButton.
<Window x:Class="WpfApplication8.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="472">
<Window.Resources>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Focusable"
Value="False" />
<Setter Property="GroupName"
Value="filter" />
<Setter Property="IsTabStop"
Value="False" />
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="HorizontalAlignment"
Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<ControlTemplate.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment"
Value="Center" />
<Setter Property="HorizontalAlignment"
Value="Center" />
</Style>
</ControlTemplate.Resources>
<Border x:Name="PART_border"
CornerRadius="2"
Margin="2"
Background="Transparent"
BorderThickness="1"
BorderBrush="{x:Static SystemColors.ControlDarkBrush}"
SnapsToDevicePixels="True">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter x:Name="PART_content" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter TargetName="PART_content"
Property="TextBlock.FontWeight"
Value="Bold" />
<Setter TargetName="PART_border"
Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,1">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="white"
Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<StackPanel Orientation="Horizontal" >
<RadioButton Height="30" Width="100" Content="First"></RadioButton>
<RadioButton Height="30"
Width="100"
Content="Second"></RadioButton>
<RadioButton Height="30"
Width="100"
Content="First"></RadioButton>
</StackPanel>
</Grid>
for RadioButton with Image just have look at Matt's blog
http://madprops.org/blog/wpf-killed-the-radiobutton-star/
You should use the built in visual state handling and create the states / styles in XAML.
In your concrete case it seems that what you're after is a group of RadioButtons, so that you don't have to write any code to deal with switching between states.
You better Use a Custom RadioButton List for this purpose.Check out the below post.
Do not allow unselect/deselect in ListBox
You can easily customize the selected and deselected styles to match your requirement
I want to change the style of a theme an inherited style (inherited through based on). Have any idea? This is basically to define multiple styles for multi-series charts in wpf toolkit. Code looks as follows:
<Style x:Key="A" TargetType="DVC:ColumnDataPoint">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DVC:ColumnDataPoint">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Opacity="0" x:Name="Root">
<Grid Background="{TemplateBinding Background}" Name="columngrid">
<Grid.Resources>
<Style x:Key="aquaboarder" TargetType="Border">
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#B211B9D8" Offset="0.1" />
<GradientStop Color="#FF0F56C7" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BackBrush}"/>
</Style>
</Grid.Resources>
<Border Name="columnBorder" BorderBrush="Transparent" BorderThickness="1" CornerRadius="20,20,0,0" Style="{StaticResource aquaboarder}">
</Border>
</Grid>
<ToolTipService.ToolTip>
<ContentControl Content="{TemplateBinding FormattedDependentValue}" />
</ToolTipService.ToolTip>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And the inherited style goes as follows:
<Style x:Key="B" BasedOn="{StaticResource A}" TargetType="DVC:ColumnDataPoint">
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#B24DE509" Offset="0.1" />
<GradientStop Color="#FF238910" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
</Style>
I want to set the columngrid in "style A" to use the backbrush defined in "style B". I do not like to do more stuff in style B as I will have many of inherited styles be defined just changing this style afterwards.
You are wasting the perfectly useful Background property that is already available and trying to create a new one that serves the same purpose. Since you are overriding the control template, just use the Background for the purpose that charting intended. Instead of setting it to transparent in your style, let your derived style set or override Background and then use {TemplateBinding Background} in the control template where are you current using {StaticResource Backbrush}. Your other use of {TemplateBinding Background} on the Grid element you can remove since it seems clear that your intention is that the grid background will be transparent.
I went from this: WPF GridViewHeader styling questions
to this:
Now I just need to get rid of the white space to the right of the "Size" header. I basically have a template for the GridViewColumnHeader that makes it a TextBlock. Is there any way I can set the background for that header area so that it spans the entire width of the GridView?
ADDED CODE:
This is my right-most column. The grid does not span 100% of available window area. In the header I need everything to the right of this column to have the same background as the column headers themselves.
<Style x:Key="GridHeaderRight" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Text="{TemplateBinding Content}" Padding="5" Width="{TemplateBinding Width}" TextAlignment="Right">
<TextBlock.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Background" Value="Green" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
<GridViewColumn Width="200" HeaderContainerStyle="{ StaticResource GridHeaderRight}" Header="Size">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=EmployeeNumber}" HorizontalAlignment="Right"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
UPDATE
I am one step closer (I think) to solving this.
I added the following code inside the GridView tag:
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="BorderBrush" Value="Green"></Setter>
<Setter Property="Height" Value="Auto"></Setter>
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
</GridView.ColumnHeaderContainerStyle>
The border is there just so you can see the boundary of what this style covers. This is an enlarged image of what this does. It seems to be what I want if I can get rid of the little white border on the bottom.
So I guess removing that tiny white bottom border would also be an accepted answer for this one.
This is a simple style that will accomplish what you are looking for. Just change the Transparent background on the Border to be your desired gradient.
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<Border BorderThickness="0,0,0,1" BorderBrush="Black" Background="Transparent">
<TextBlock x:Name="ContentHeader" Text="{TemplateBinding Content}" Padding="5,5,5,0" Width="{TemplateBinding Width}" TextAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
</Style>
sometimes the simplest way is the best. All you need to do it to change the TextBlock attached properties of GridViewColumnHeader
Define something like this in Resources:
<Style TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource {x:Type GridViewColumnHeader}}">
<Setter Property="TextBlock.TextWrapping" Value="Wrap"/>
<Setter Property="TextBlock.Foreground" Value="Black"/>
</Style>
Have a look at the GridViewColumnHeader.Role property. The sample in the documentation for the GridViewColumnHeaderRole enumeration might give you some ideas...
EDIT: Have you considered using the GridView.HeaderStyle property ?
I solved this issue but I think there should be a better way of doing it. The problem was that I had TextBlocks on the header of each column. The unused area didn't have anything on the header row. I just added a TextBlock with the same background in the GridView.ColumnHeaderContainerStyle and it happened to span the rest of the unused width of the grid.
<GridView.ColumnHeaderContainerStyle>
<Style TargetType="GridViewColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
<TextBlock Text="" Padding="5">
<TextBlock.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0.0" Color="#373638" />
<GradientStop Offset="1.0" Color="#77797B" />
</LinearGradientBrush>
</TextBlock.Background>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GridView.ColumnHeaderContainerStyle>