Applying border style on certain grid cells in WPF - c#

I want to apply the following style to certain cells of my grid:
<Border BorderBrush="#808080" BorderThickness="1,1,0,0" Grid.Column="3" >
<Border BorderBrush="#404040" BorderThickness="1,1,0,0" Width="Auto">
<Border BorderBrush="#FFFFFF" BorderThickness="0,0,1,1" Width="Auto">
<Border BorderBrush="#DCE6F4" BorderThickness="0,0,1,1" Width="Auto">
</Border>
</Border>
</Border>
</Border>
Right now i specify the cell in the first line Grid.Colum="3". However to do this for all cells I have to copy paste this like 20 times. Is there any short way to apply my style to all controls or cells of my choice (for example cell 1, , 7, 9 or label1, label 9 and label10?
I am a newbie in wpf, please be gentle :)

Assuming you want to place labels inside the grid you could create a ControlTemplate and assign it to the labels you want with Template="{StaticResource BorderLabel}":
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<ControlTemplate TargetType="Label" x:Key="BorderLabel">
<Border BorderBrush="#808080" BorderThickness="1,1,0,0" >
<Border BorderBrush="#404040" BorderThickness="1,1,0,0" Width="Auto">
<Border BorderBrush="#FFFFFF" BorderThickness="0,0,1,1" Width="Auto">
<Border BorderBrush="#DCE6F4" BorderThickness="0,0,1,1" Width="Auto">
<ContentControl Content="{TemplateBinding Content}" />
</Border>
</Border>
</Border>
</Border>
</ControlTemplate>
</Grid.Resources>
<Label Grid.Column="0" Content="MyText" />
<Label Grid.Column="1" Content="MyText" Template="{StaticResource BorderLabel}" />
</Grid>
And this is how it looks:

Related

How can I make controls in WPF stretch to fill available width when HorizontalAlignment and HorizontalContentAlignment don't work?

I'm trying to make a simple WPF app that has sections that fill the available width. Despite trying various ways of stretching the width of elements, containers, and children, nothing is working and I can't figure out why.
Another question said to use uniformgrid which worked well EXCEPT that it set the height of all the elements uniformly which was definitely not what I wanted. I want all of the sections to look like the one in the picture - filled width, height auto based on the content. Here's the basic setup:
<Window x:Class="A_Customizer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:A_Customizer"
mc:Ignorable="d"
Title="MainWindow"
Background="#FF2B2B2B"
Width="800"
>
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Name="mainApp" >
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<WrapPanel Grid.Row="0" >
<Button ToolTip="Click to apply the below settings to this Jumpbox" Click="ApplyCustomizations">Customize</Button>
</WrapPanel>
<ScrollViewer Grid.Row="1">
<WrapPanel HorizontalAlignment="Stretch" >
<GroupBox
Background="#FFE2E2E2"
BorderBrush="#FF7F7F7F"
Margin="10,10,10,10"
Name="pathsBox"
HorizontalContentAlignment="Stretch"
HorizontalAlignment="Stretch"
>
<GroupBox.Header>
<Border Background="#FFAFAFAF" CornerRadius="3">
<Label FontWeight="Bold">Key Paths</Label>
</Border>
</GroupBox.Header>
<StackPanel HorizontalAlignment="Stretch">
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBox Name="homeFolder" Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
<Button Grid.Column="1" Click="NewQuickPath" ToolTip="Change home folder">
<Image Source="images\add_folder.png" Height="25" Cursor="Hand"></Image>
</Button>
</Grid>
<TextBox Name="progFolder" Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
</StackPanel>
</GroupBox>
<GroupBox
Background="#FFE2E2E2"
BorderBrush="#FF7F7F7F"
Margin="10,10,10,10"
Name="quickBox"
Height="auto"
HorizontalContentAlignment="Stretch"
>
<GroupBox.Header>
<Border Background="#FFAFAFAF" CornerRadius="3">
<Label FontWeight="Bold">Quick Access Folders</Label>
</Border>
</GroupBox.Header>
<StackPanel HorizontalAlignment="Stretch">
<TextBlock TextWrapping="Wrap" Margin="15">
There are going to be folders you'll need to access frequently and keeping them pinned on top of the left menu in Explorer is helpful.
Select here to add them to the list of folders restored with the "Customize" button. Click any folder to remove it.
</TextBlock>
<Border CornerRadius="3" Background="#FFF3C7C7" Margin="6" Visibility="Collapsed" Name="quickErr" Tag="err_box">
<TextBlock Tag="errMsg" Foreground="#FFFD3434" TextWrapping="Wrap" Margin="6" ></TextBlock>
</Border>
<UniformGrid Name="quickPathsArea" Columns="1">
</UniformGrid>
<Grid Margin="0,10,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" HorizontalAlignment="Stretch"></TextBox>
<Button Grid.Column="1" Click="NewQuickPath" ToolTip="Add a new folder">
<Image Source="images\add_folder.png" Height="25" Cursor="Hand"></Image>
</Button>
</Grid>
</StackPanel>
</GroupBox>
</wrappanel>
</scrollviewer>
</grid>
StackPanel with Orientation="Vertical" (default value) instead of WrapPanel should work: it will allow each child element use full width and as much height as necessary

How to change the toggle of a TreeView

I have a treeview working, it has a toggle button that can expand it's contents. When I do, each column is too far to the right from where I want it due to the toggle expansion width. I'd like to override that behaviour but I don't know how, I understand it's something to do with defining the control template of the TreeView?
This is my code
c#
Class MyList
{
double someDouble;
double somestring;
souble anotherString;
bool thisOnesABool;
}
Class MyContainer
{
string headerText1;
string headerText2;
List<MyList> SomeList;
}
List<MyContainer> SomeContainerInCodeBehind = new List<MyContainer>();
WPF
<UserControl.Resources>
<DataTemplate x:Key="level2">
<Grid>
//the content of 'MyList'
</Grid>
</DataTemplate>
<HierarchicalDataTemplate x:Key="level1"
ItemsSource="{Binding SomeListWithinContainer}"
ItemTemplate="{StaticResource level2}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding HeaderText}" />
<TextBox Grid.Column="1" Text="{Binding MoreHeaderText}" />
</Grid>
</HierarchicalDataTemplate>
</UserControl.Resources>
<Grid>
<TreeView Name="TheTreeView"
Grid.Row="1"
ItemTemplate="{StaticResource level1}"
ItemsSource="{Binding SomeContainerInCodeBehind}">
</TreeView>
</Grid>
In order to change the position of the expander (or expanded child items), you have to override the ControlTemplate of the TreeViewItem.
The following Style is taken from Microsoft Docs: TreeView Styles and Templates and shortened to show the relevant code. Visit the link to get the full code.
<Style x:Key="{x:Type TreeViewItem}"
TargetType="{x:Type TreeViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19"
Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
...
</VisualStateManager.VisualStateGroups>
<!-- Use Margin to modify the position of the "Expander" ToggleButton -->
<ToggleButton x:Name="Expander"
Style="{StaticResource ExpandCollapseToggleStyle}"
ClickMode="Press"
IsChecked="{Binding IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"/>
<Border x:Name="Bd"
Grid.Column="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<!-- Modify e.g. Margin to change the position of the Header (parent item) -->
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<!-- Modify e.g. using Margin to reposition the expanded child items -->
<ItemsPresenter x:Name="ItemsHost"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"
Visibility="Collapsed" />
</Grid>
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

C# WPF Grid Columns misinterpreted

I've started developing a new application in WPF C#. The problem I'm having is regarding grid column definitions.
I have divided my Window into separate sections, using Grids' row and col definitions (see code below).
I have two rows. First is currently empty, second one contains a new grid, that is further divided into columns.
All grids are inside a border.
The weird behavior I'm getting, is this section of the code:
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="1">
<Grid>
</Grid>
</Border>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="2">
<Grid>
</Grid>
</Border>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="3">
<Grid>
</Grid>
</Border>
The problem is, that the first "subgrid" actually corresponds to the
second column, The second and third both refer to the third column.
In other words, whenever I put any kind of control in the second subgrid (the one which has Grid.Column="2"), the control will appear in the third column for some reason.
I've been fiddling around with it, and can't seem to understand the behavior I'm getting.
Another example: I've put a control in the second column as following:
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="2">
<Grid>
<TextBox Width="100" Height="50"></TextBox>
</Grid>
</Border>
The image below represents what I got:
Whole XAML code:
<Border BorderThickness="1" BorderBrush="#ffcd22" Margin="10,10,10,10">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border BorderThickness="1" BorderBrush="#ffcd22" Margin="-1,-1,-1,-1" Grid.Row="2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="1">
<Grid>
</Grid>
</Border>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="2">
<Grid>
</Grid>
</Border>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="3">
<Grid>
</Grid>
</Border>
</Grid>
</Border>
</Grid>
The problem is that the column numeration starts from 0. You should change your code like this:
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="0">
<Grid>
</Grid>
</Border>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="1">
<Grid>
</Grid>
</Border>
<Border BorderThickness="1" BorderBrush="#ffcd22" Grid.Column="2">
<Grid>
</Grid>
</Border>

How do I correctly format the DatePicker StyleTemplate

I need to format an UWP-DatePicker. What I'd like to get would be a common DatePicker which fits inside a grid propperly.
Here is how I embedded the DatePicker inside my GridColumn:
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<DatePicker Grid.Column="0"
HorizontalAlignment="Left"
MonthFormat="{}{month.abbreviated(3)}"
Date="{Binding AppointmentStartDateProxy, Mode=TwoWay}"
DateChanged="DatePicker_DateChanged"
Style="{StaticResource DatePickerStyle1}">
<DatePicker.IsEnabled>
<Binding Path="Closed" Converter="{StaticResource negationConverter}"/>
</DatePicker.IsEnabled>
</DatePicker>
</Grid>
Here are the "crucial" changes to the StyleTemplate:
<Style x:Key="DatePickerStyle1" TargetType="DatePicker">
<.../>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DatePicker">
<StackPanel x:Name="LayoutRoot" Margin="{TemplateBinding Padding}" HorizontalAlignment="Stretch" >
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Visibility="Collapsed"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Margin="0,0,0,8"
Foreground="{ThemeResource SystemControlForegroundBaseHighBrush}"
AutomationProperties.AccessibilityView="Raw" />
<Button x:Name="FlyoutButton"
HorizontalAlignment="Left"
Style="{StaticResource DatePickerFlyoutButtonStyle}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
IsEnabled="{TemplateBinding IsEnabled}"
HorizontalContentAlignment="Stretch" />
When setting Style.Setter.Value.ControlTemplate.StackPanel.Button.HorizontalAlignment="Left"
my DatePicker does not fill its parent control:
When setting Style.Setter.Value.ControlTemplate.StackPanel.Button.HorizontalAlignment="Strech" my DatePicker is overlapping its parent control:
This behavior also stays the same when I'm changing the StyleTemplates LayoutRoot from StackPanel to Grid.
In my understanding, the RootLayout-Control should inherit its size from the Grid containing the DatePicker, and the Button should get its size from RootLayout with an result in fitting inside my GridColumn.
EDIT:
When changing only the DatePickers HorizontalAlignment to Strech (and in abscense of a style) it's overlapping the parent grid way to far:
Actually you don't need to change the style or the Button alignments. All you need is to set the HorizontalAlignment to Stretch in both controls. Note that the default value of it is Left.
<Grid x:Name="LayoutRoot">
<Grid Width="800">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<DatePicker Grid.Column="0" MonthFormat="{}{month.abbreviated(3)}" HorizontalAlignment="Stretch" />
<TimePicker Grid.Column="1" HorizontalAlignment="Stretch" />
</Grid>
</Grid>
Update
One more thing. DatePicker has a default MinWidth of 296 and TimePicker of 242. So if you could set them to a smaller value, like this -
<DatePicker Grid.Column="0" MonthFormat="{}{month.abbreviated(3)}" HorizontalAlignment="Stretch" MinWidth="80" />
<TimePicker Grid.Column="1" HorizontalAlignment="Stretch" MinWidth="80" />

Styled Expander Control Template and not able to view Expanded Content on Click

I am just styling the Expander Control in WPF. I have defined only the styles in Expander Control Template, but I am not able to view the content of expander when I click on it.
I guess I have to define the expander trigers also ? but I don't know which triger and how to define it.
Also why I have to define triggers when I am just styling the expander.
<Window x:Class="ExpanderControl.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>
<Style TargetType="Expander">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="0" Name="contentRow"></RowDefinition>
</Grid.RowDefinitions>
<!--Expander Header-->
<Border Background="AliceBlue"
Grid.Row="0"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" ContentSource="Header"
RecognizesAccessKey="True"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="5"
></ContentPresenter>
<ToggleButton Grid.Column="1">
<TextBlock>x</TextBlock>
</ToggleButton>
</Grid>
</Border>
<!--Expander Content-->
<Border Background="Aqua" Grid.Row="1">
<ContentPresenter Grid.Row="1"></ContentPresenter>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<Expander Header="Expander" HorizontalAlignment="Left" Margin="205,95,0,0" VerticalAlignment="Top" Width="200">
<Grid Background="#FFE5E5E5">
<Menu>
<MenuItem Header="hi"></MenuItem>
</Menu>
</Grid>
</Expander>
</Grid>
</Window>
At the moment there is no action linked to ToggleButton. You need to utilize Expander.IsExpanded property by binding it
To ToggleButton.IsChecked
To Border.Visibility via BooleanToVisibilityConverter (custom or built in)
Set content row height to Auto
This way changing ToggleButton.IsChecked will change Expander.IsExpanded which in turn will affect visibility of content Border. It will also work when you change IsExpanded property from outside.
This is working XAML
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<Style TargetType="{x:Type Expander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto" Name="contentRow"/>
</Grid.RowDefinitions>
<!--Expander Header-->
<Border Background="AliceBlue" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" />
<ToggleButton Grid.Column="1" Content="x" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"/>
</Grid>
</Border>
<!--Expander Content-->
<Border Background="Aqua" Grid.Row="1" Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded, Converter={StaticResource BooleanToVisibilityConverter}}">
<ContentPresenter/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
EDIT
If you want whole header to be able to expand/collapse your Expander you need to bring ContentPresenter for Header into Content of ToggleButton. In your case basically bring header Grid into ToggleButton.Content
<!--Expander Header-->
<ToggleButton IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}" HorizontalContentAlignment="Stretch" Grid.Row="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="20"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0" ContentSource="Header" RecognizesAccessKey="True" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5" />
<TextBlock Grid.Column="1" Text="x" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ToggleButton>

Categories

Resources