Center checkbox in UniformGrid's cells in WPF - 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

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 change the header background of a GroupBox?

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.

Why in my WPF view is the Content text of my Label control not visible?

I have the following markup:
<StackPanel Grid.Row="0" Orientation="Horizontal">
<StackPanel Orientation="Horizontal" Visibility="{Binding OrgListVisibility}">
<Label Content="Org:" />
<ComboBox ItemsSource="{Binding OrgSelectList, NotifyOnSourceUpdated=True}" SelectedValuePath="Key" DisplayMemberPath="Value" SelectedItem="{Binding OrgId}" />
</StackPanel>
<StackPanel Orientation="Horizontal" Visibility="{Binding BranchListVisibility}">
<TextBlock Text="Branch:" Style="{StaticResource FormLabel}" />
<ComboBox x:Name="BranchList" ItemsSource="{Binding BranchSelectList}" SelectedValuePath="Key" DisplayMemberPath="Value" SelectedItem="{Binding BranchId}" />
</StackPanel>
</StackPanel>
Yet when I run the app, only the text from the TextBlock is visible, and not that of the Label. The latter is in the Visual Tree, with a TextBlock deep down, but that is as far as I can see.
AS REQUESTED: Here is the style for FormLabel:
<Style TargetType="TextBlock" x:Key="FormLabel">
<Setter Property="Height" Value="20" />
<Setter Property="Margin" Value="10" />
<Setter Property="TextAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
A SIMILAR PROBLEM:
I found an almost similar problem with a combobox when I bound it to a collection of instances of a generic class. The items' text simply did not show, but they were present in the comboboxes. Selecting on the one by knowing the position of my sought item correctly cascaded to the 2nd combobox, which had visible items, and I could see the correct but invisible item had been selected.
As soon as I change the item source to a list of non-generic objects, the items in the dropdown were visible again.
The code looks fine and as you have mentioned in the comments section that it takes layout space then it may very well happen that the color of your label and the background color of the containing layout be same.
To troubleshoot this, try giving some different background and foreground colors e.g. red or blue to the Label. Hope this helps
Ctrl+Q -> Live Visual Tree
Then hit the "pick element" button and select your label. Check the following properties:
Visibility
Opacity
Content
Also check the child elements of the Label. Setting the Content should result in a tree like this:
If a default style has changed the control template, you might not see the TextBlock as a child here. Also drill into the TextBlock and make sure it has the right Text property, then make sure it and all its parents have the right Opacity and Visibility . Also make sure that the inner TextBlock has space allocated to it by selecting it and turning on the highlighting feature in the live visual tree window.
Can you try this code to see if it works?
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0"
Orientation="Horizontal" Visibility="{Binding OrgListVisibility}">
<Label Content="Org:" />
<ComboBox ItemsSource="{Binding OrgSelectList, NotifyOnSourceUpdated=True}"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding OrgId}" />
</StackPanel>
<StackPanel Grid.Column="1"
Orientation="Horizontal" Visibility="{Binding BranchListVisibility}">
<TextBlock Text="Branch:" Style="{StaticResource FormLabel}" />
<ComboBox x:Name="BranchList"
ItemsSource="{Binding BranchSelectList}"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding BranchId}" />
</StackPanel>
</Grid>
The Label would take up layout space while not being visible when its Visibility == Hidden. You should check and make sure that your application does not define a global style (one with no Key) for TargetType="Label" where this value could be set:
<Style TargetType="Label"> !!!note that this has no 'Key' associated
[...]
<Setter Property="Visibility" Value="Hidden" />
[...]
</Style>
This would not need to be in the same xaml file in order to be automatically applied, you should check the global dictionary or any other ResourceDictionary linked in the file.
I had the same problem. It turned out that the label Height was too small. Increased the height and its content became visible.

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">

Difference between Control Template and DataTemplate in WPF

What is difference between a ControlTemplate and a DataTemplate in WPF?
Typically a control is rendered for its own sake, and doesn't reflect underlying data. For example, a Button wouldn't be bound to a business object - it's there purely so it can be clicked on. A ContentControl or ListBox, however, generally appear so that they can present data for the user.
A DataTemplate, therefore, is used to provide visual structure for underlying data, while a ControlTemplate has nothing to do with underlying data and simply provides visual layout for the control itself.
A ControlTemplate will generally only contain TemplateBinding expressions, binding back to the properties on the control itself, while a DataTemplate will contain standard Binding expressions, binding to the properties of its DataContext (the business/domain object or view model).
Very basically a ControlTemplate describes how to display a Control while a DataTemplate describes how to display Data.
For example:
A Label is a control and will include a ControlTemplate which says the Label should be displayed using a Border around some Content (a DataTemplate or another Control).
A Customer class is Data and will be displayed using a DataTemplate which could say to display the Customer type as a StackPanel containing two TextBlocks one showing the Name and the other displaying the phone number. It might be helpful to note that all classes are displayed using DataTemplates, you will just usually use the default template which is a TextBlock with the Text property set to the result of the Object's ToString method.
Troels Larsen has a good explanation on MSDN forum
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate x:Key="ButtonContentTemplate">
<StackPanel Orientation="Horizontal">
<Grid Height="8" Width="8">
<Path HorizontalAlignment="Stretch"
Margin="0,0,1.8,1.8"
VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FF000000"
Data="M0.5,5.7 L0.5,0.5 L5.7,0.5"/>
<Path HorizontalAlignment="Stretch"
Margin="2,3,0,0"
VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FFFFFFFF"
Data="M3.2,7.5 L7.5,7.5 L7.5,3.5"/>
<Path HorizontalAlignment="Stretch"
Margin="1.2,1.4,0.7,0.7"
VerticalAlignment="Stretch" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000"
Data="M2.5,2.5 L7.5,7.5"/>
<Path HorizontalAlignment="Stretch"
Margin="1.7,2.0,1,1"
VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FF000000"
Data="M3,7.5 L7.5,7.5 L7.5,3.5"/>
<Path HorizontalAlignment="Stretch"
Margin="1,1,1,1"
VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FFFFFFFF"
Data="M1.5,6.5 L1.5,1 L6.5,1.5"/>
</Grid>
<ContentPresenter Content="{Binding}"/>
</StackPanel>
</DataTemplate>
<ControlTemplate TargetType="Button" x:Key="ButtonControlTemplate">
<Grid>
<Ellipse Fill="{TemplateBinding Background}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Window.Resources>
<StackPanel>
<Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="1"/>
<Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="2"/>
<Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="3"/>
</StackPanel>
</Window>
(Templates blatently stolen from
http://msdn.microsoft.com/en-us/library/system.windows.controls.controltemplate.aspx
and
http://msdn.microsoft.com/en-us/library/system.windows.controls.contentcontrol.contenttemplate%28VS.95%29.aspx
respectively)
Anyway, the ControlTemplate decides how the Button itself looks, while
the ContentTemplate decides how the Content of the button looks. So
you could bind the content to one of you data classes and have it
present itself however you wanted it.
ControlTemplate: Represents control style.
DataTemplate: Represents data style(How would you like to show your data).
All controls are using default control template that you can override through template property.
For example
Button template is a control template.
Button content template is a data template
<Button VerticalAlignment="Top" >
<Button.Template>
<ControlTemplate >
<Grid>
<Rectangle Fill="Blue" RadiusX="20" RadiusY="20"/>
<Ellipse Fill="Red" />
<ContentPresenter Content="{Binding}">
<ContentPresenter.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="50">
<TextBlock Text="Name" Margin="5"/>
<TextBox Text="{Binding UserName, Mode=TwoWay}" Margin="5" Width="100"/>
<Button Content="Show Name" Click="OnClickShowName" />
</StackPanel>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
public String UserName
{
get { return userName; }
set
{
userName = value;
this.NotifyPropertyChanged("UserName");
}
}
ControlTemplate - Changing the appearance of element. For example Button can contain image and text
DataTemplate - Representing the underlying data using the elements.
ControlTemplate DEFINES the visual appearance, DataTemplate REPLACES the visual appearance of a data item.
Example: I want to show a button from rectangular to circle form => Control Template.
And if you have complex objects to the control, it just calls and shows ToString(), with DataTemplate you can get various members and display and change their values of the data object.
All of the above answers are great but there is a key difference that was missed. That helps make better decisions about when to use what. It is ItemTemplate property:
DataTemplate is used for elements that provide ItemTemplate property for you to replace its items' content using DataTemplates you define previously according to bound data through a selector that you provide.
But if your control does not provide this luxury for you then you still can use a ContentView that can display its content from predefined ControlTemplate. Interestingly, you can change the ControlTemplate property of your ContentView at runtime. One more thing to note that unlike controls with ItemTemplate property, you cannot have a TemplateSelector for this (ContentView) control. However, you still can create triggers to change the ControlTemplate at runtime.

Resources