How to change the header background of a GroupBox? - wpf

How can I change the Background of the header of a GroupBox?
I'm trying to do that with:
<GroupBox Grid.Row="0">
<GroupBox.Header>
<Setter Property="Background" //<- no backgroundproperty
there is no Background property

You can define a Border in the Header and set the Background of it to your desired color:
<GroupBox >
<GroupBox.Header>
<Border Background="Red">
<Label Content="Hello"></Label>
</Border>
</GroupBox.Header>
</GroupBox>

You could set the Header property to any UI element including a Grid or a Border for example:
<GroupBox>
<GroupBox.Header>
<Border Background="Green">
<TextBlock Text="header..." />
</Border>
</GroupBox.Header>
<TextBlock Text="content..."></TextBlock>
</GroupBox>

Take a look at this site: Control Templates, Styles, and Triggers
this is probably more than you need, but it explains how to use a control template to modify controls in various ways. I use this particular control (with different colors) for groupboxes on one of my applications, and it has come in very handy.

Related

Strange border still resding on button; even after modifying the control template

I have a 'feedback' button which has this strange border:
So I searched online for some solutions and modified the control template, and I got this:
Control Template code:
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
So even after modifying the control template - I am getting a strange brown border. Help would be appreciated regarding this.
Button code:
<Button Grid.Row="3"
Grid.Column="2"
Grid.RowSpan="2"
Style="{StaticResource IconStyleBase}"
Name="Feedback_Button">
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="218*" />
<RowDefinition Height="68*" />
</Grid.RowDefinitions>
<!--Icon-->
<Button Background="#3767B0"
Style="{StaticResource IconStyleContent}">
<!--Content-->
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<TextBlock Padding="55"></TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
<!--Icon Text-->
<Button Background="#FF2D5BA0"
Style="{StaticResource IconStyleSubBase}">
<!--Content-->
<Button.ContentTemplate>
<DataTemplate>
<Viewbox>
<TextBlock Padding="15">Feedback</TextBlock>
</Viewbox>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</Grid>
</Button>
A DataTemplate defines the appearance of the the items that you set as Content of a button, but the button itself as a container has a default style and control template that defines how it looks like, along with its different states like mouse-over or pressed. That is where the border comes from.
You can try to create a style that sets the BorderThickness to 0 and apply it on each of your buttons. This approach works for control templates that bind the border thickness from their templated parent.
<Style x:Key="BorderlessButtonStyle" TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="BorderThickness" Value="0"/>
</Style>
If this does not work or you want adapt the appearance of your buttons in detail, you have to extract and adapt the button style and control template.
Your custom control template does not work, because you did not apply it to the inner buttons and you should remove Content="{TemplateBinding Content}". Nevertheless, your button control template does not define any control states, so it will not be responsive at all.
You should copy the control template for Button from here, or extract it manually via Blend or Visual Studio. Then you can remove or the Border within it, change its thickness or color, so it will disappear. Moreover, you can adapt its various states to fit your desired style.
A notice on your design. It do not think that it is a good idea to nest buttons. Your control should either be a single button or a panel with two buttons in it, but that also only makes sense if they execute different actions in a related context, like split buttons do.

How To Make A WPF UserControl Act As A Container

I'm trying to create a Toolbar control that can group selected buttons with a border and a label. If there is already a built-in control that will do this then I could use that instead of building a UserControl.
If not, then what I'm wanting to build is a UserControl that would allow me to enter one-to-many of my ImageButton UserControls and set a GroupLabel text like below. Can this be done in WPF?
<User_Controls:ToolbarGroup GroupLabel="Entity">
<User_Controls:ImageButton ButtonText="Entity Setup"/>
<User_Controls:ImageButton ButtonText="New Entity"/>
</User_Controls:ToolbarGroup>
PS: I would post an image but this quirky forum won't allow me to post an image.
If i have got you correctly then I think you can achieve this way also, and on mouse eneter and leave event you can do the button click job.
for setting text you can use a grid and a label inside it to set the text, and Image buttons below it.
<UserControl x:Class="ABC.View.Oats"
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>
<Image Source="{Binding Image}" Stretch="Fill"/>
</Grid>
</UserControl>
I think what you're looking for is a GroupBox, it has a header property where you can set the label.
Something like this:
<GroupBox Width="300" Height="100">
<GroupBox.Header>
<Label>Text</Label>
</GroupBox.Header>
<StackPanel>
<Button Content="Button"/>
<Button Content="Button"/>
<Button Content="Button"/>
</StackPanel>
</GroupBox>
I would also recommend using the groupbox, it seems to be doing exactly what you want it to do and it looks neat. Here's some examples on how to use them: http://www.dotnetperls.com/groupbox-wpf
On the other hand, if you believe the groupbox is not sufficient, you could create a control that inherits from the groupbox and you could extend it and add whatever you need to it. It would look like this:
public class customGroupBox: GroupBox{
....Add whatever you need here
}
Thanks for the replies. I tried the GroupBox and it's not the layout we want because we want the label underneath the buttons and centered. I never could find a way to add a collection to the UserControl. Maybe I didn't ask the question right by calling it a container. The code below will work, but it's not elegant. I wanted something that would wrap the layout in a UserControl and allow me to add a variable number of buttons to each toolbar group.
<StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 1"/>
<User_Controls:ImageButton ButtonText="New 2"/>
<User_Controls:ImageButton ButtonText="New 3"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 1"/>
</StackPanel>
</Border>
<Border Background="GhostWhite" BorderBrush="Gainsboro" BorderThickness="1">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<User_Controls:ImageButton ButtonText="New 4"/>
</StackPanel>
<Label HorizontalAlignment="Center" Content="Group 2"/>
</StackPanel>
</Border>
</StackPanel>
One way to accomplish this is with a custom styled ItemsControl.
You can then reuse it and just bind it to different data.
Please forgive me, this is hand-typed...
In your resources...
<Style x:Key="ToolbarGroupItemsControlStyle" TargetType="ItemsControl">
...
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ItemsControl">
<Grid>
... XAML to form your group with a binding to the
... group name
<ItemsPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ToolbarGroupItemTemplate">
<Grid>
... XAML and binding for each toolbar group item ...
</Grid>
</DataTemplate>
In your XAML...
<ItemsControl
Style="{DynamicResource ToolbarGroupItemsControlStyle}"
ItemsSource="{Binding ToolbarGroupItems}"
ItemTemplate="{DynamicResource ToolbarGroupItemTemplate"/>
If your resources above are at the application level, then you can place the ItemsControl above on any Window/UserControl you want.
Your ItemsSource will need to be a collection of a custom type you create that has bindings for the button text, etc.
I hope this is helpful.

WPF VisualStateManager Changing Child Properties

I have a ScrollViewer with some nested child elements like this:
<ScrollViewer x:Name="MainScrollViewer"...>
<Grid ...>
<TextBlock ... FontSize="20" ...>
<StackPanel ...>
<TextBlock ... FontSize="15" ...>
...
<TextBlock ... FontSize="15" ...>
</StackPanel ...>
</Grid>
</ScrollViewer>
Most of the TextBlocks have a FontSize set explicitly in the control.
I'm writing a Windows Universal app and so I am using the Visual State Manager to take care of different window sizes. I need to change the font size of all child elements within MainScrollViewer for one of the visual states.
I tried setting the FontSize using one of the setters for a particular visual state as such:
<Setter Target="MainScrollViewer.FontSize" Value="10">
This seems to have no effect, as it is not overriding the values. How can I override all font sizes of child elements using a VSM Setter?
If no better solution comes up you could take one TextBlock as the font size master and all other TextBlocks bind to that master. Doing so you only need to set the font size of the master in the VSM.
<TextBlock x:Name="FonSizeMaster" FontSize="20" ... />
<TextBlock FontSize="{Binding FontSize, ElementName=FonSizeMaster}" .../>
MSDN has a good example for VSM
Manages states and the logic for transitioning between states for controls.
https://msdn.microsoft.com/en-us/library/system.windows.visualstatemanager(v=vs.110).aspx
Since FontSize is an attached property the following should also work (not tested):
<ScrollViewer x:Name="MainScrollViewer" TextElement.FontSize="20" ...>
<Grid ...>
<TextBlock ... >
<StackPanel ...>
<TextBlock ... >
...
<TextBlock ... >
</StackPanel ...>
</Grid>
</ScrollViewer>
VSM:
<Setter TargetName="MainScrollViewer" Property="TextElement.FontSize" Value="10">

Center checkbox in UniformGrid's cells in WPF

I want to center and stretch checkbox in UniformGrid's cell.
I've tried to do it in many ways:
<UniformGrid>
<CheckBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Center" VerticalContentAlignment="Center" />
<CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" />
<CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" ClipToBounds="True" />
<CheckBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ClipToBounds="True" />
Selected cell (0, 0):
Selected cell (1, 0):
but it doesn't satisfy me because I want to stretch (just like in cell (0,0)) and center (just like in (1,0)) those checkboxes in their cells simultaneously.
How can I do it?
[edit 1]
I'm trying to make it so that I don't have to click the little check but instead can click the entire cell.
[edit 2]
Actually I want to add those checkboxes from C# code so if solution made in XAML is not 'portable' to C# language it will be not very helpful.
If I use this simple markup with the default Stretch values:
<UniformGrid>
<CheckBox Content="This is a checkbox" />
<CheckBox Content="This is a checkbox" />
<CheckBox Content="This is a checkbox" />
<CheckBox Content="This is a checkbox" />
</UniformGrid>
I am able to click anywhere in each cell of the UniformGrid to check and uncheck the Checkbox in that cell.
Functionally this is doing what you want. if you want to change the appearance of the checkbox, you can use a ControlTemplate.
If you don't want to change the size of the CheckBox and you just want to center it visually while being able to click the cell to check it, you could use a template like this:
<CheckBox>
<CheckBox.Template>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid Background="Transparent">
<CheckBox IsChecked="{TemplateBinding Property=IsChecked}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
EDIT:
To apply it as a resource at runtime, write the XAML in a resource section of the appropriate scope. You can place it in the local Resources dictionary if you only need it in one control, or if you want access to it globally, put it in the App.xaml like so:
<Application.Resources>
<ControlTemplate x:Key="StretchedCheckBox" TargetType="{x:Type CheckBox}">
<Grid Background="Transparent">
<CheckBox IsChecked="{TemplateBinding Property=IsChecked}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Application.Resources>
Notice how it has a key "StretchedCheckBox". Now you can use that to apply it in code:
ControlTemplate stretchedTemplate = FindResource("StretchedCheckBox") as ControlTemplate;
CheckBox chkBox = new CheckBox();
chkBox.Template = stretchedTemplate;
I don't think you can affect the size of a CheckBox like that because the size is pre-determined in the control template
One solution would be to use a LayoutTransform to scale the CheckBox to be larger
<CheckBox>
<CheckBox.LayoutTransform>
<ScaleTransform ScaleX="5" ScaleY="5" />
</CheckBox.LayoutTransform>
</CheckBox>
It should be noted that this scales the text next to the CheckBox as well as the CheckBox itself, and sometimes doesn't look very nice depending on how you scale it.
Another alternative solution is to copy the example CheckBox template from MSDN, and create a larger CheckBox

Getting a Border Control to Have Sunken Border

I want my to have a sunken border like a textbox. How to do this? Is there a way to get the controltemplate to mimc the parent border?
There is no theme for you to use, but you can work around like this:
Using this MSDN model (http://i.msdn.microsoft.com/dynimg/IC84967.gif):
Here's my recommendation: (sunken inner)
Just change the height/width of the outside border and you use this block of XAML like a TextBox. Reverse the two border tags if you want an outder border instead. Should be easy for you.
<Border Width="100" Height="200"
BorderBrush="Gainsboro" BorderThickness="0,0,5,5">
<Border BorderBrush="Gray" BorderThickness="5,5,0,0">
<TextBox Text="Hello World"
BorderThickness="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Border>
</Border>
Special thanks to: Style a border with a different brush color for each corner
Should look like this:
You can try something like this
<Border Margin="20" BorderThickness="0.5" BorderBrush="Gray">
<Border BorderThickness="1,1,0,0" BorderBrush="DarkGray">
<ContentPresenter />
</Border>
</Border>
You might need to play with the colours though.

Resources