Styling a button in xaml - c#

I am trying to make a style for some buttons, at first I made one style for the buttons but then I needed an icon in them so i put the icon in the style.
However that is not the way to go, I can't get the icon in the button but out of the style.
code in style:
<Style x:Name="stlBtnOpen" x:Key="stlBtnOpen" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="borderBtnOpen" CornerRadius="10" BorderBrush="DarkGray" BorderThickness="1" Background="Transparent">
<Grid Background="{DynamicResource AccentColorBrush}" Margin="6">
<Grid.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_folder}"/>
</Grid.OpacityMask>
</Grid>
</Border>
<ControlTemplate.Triggers>
//some events
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
code in element:
<Button Grid.Column="2" x:Name="btnOpen" Click="btnOpen_Click">
<Border x:Name="borderBtnOpen" CornerRadius="10" BorderBrush="DarkGray" BorderThickness="1" Background="Transparent">
<Grid Background="{DynamicResource AccentColorBrush}" Margin="6">
<Grid.OpacityMask>
<VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_folder}"/>
</Grid.OpacityMask>
</Grid>
</Border>
</Button>

*Did you try to put the image in the grid you put in you button's content :
<Button Grid.Column="2" x:Name="btnOpen" Click="btnOpen_Click">
<Border x:Name="borderBtnOpen" CornerRadius="10" BorderBrush="DarkGray" BorderThickness="1" Background="Transparent">
<Grid Background="{DynamicResource AccentColorBrush}" Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0">
<Rectangle.Fill>
<VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_folder}"/>
</Rectangle.Fill>
</Rectangle>
<Textblock Grid.Column="1"/>
</Grid>
</Border>
</Button>
Got that from memory, but it shouldn't be too far from what you need (you might also replace the grid with a stackpanel that would reduce the boilerplate from the columns definitions)
Ah and don't forget to put something into the textblock if you want to have something in your button :)
EDIT :
Well this IS working for me, but there are a coupe of issues inherent to using a brush to fill another object.
But first here is the EXACT working markup
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<Button x:Name="btnOpen"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Click="">
<Border x:Name="borderBtnOpen"
Background="Transparent"
BorderBrush="DarkGray"
BorderThickness="1"
CornerRadius="10">
<Grid Margin="6"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="{DynamicResource AccentColorBrush}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Width="20px">
<Rectangle.Fill>
<SolidColorBrush Color="Blue"/>
</Rectangle.Fill>
</Rectangle>
<TextBlock Grid.Column="1" Text="bonjour"/>
</Grid>
</Border>
</Button>
</Grid>
</Window>
There are 2 issues here :
The Border will not extend itself to the button size (you can see it if you force a larger width than what the button really needs)
You will have to manually define the rectangle's size (the brush only fill and does not define it's size) or else, you will have a rectangle with a 0px size which is effectively non existent on screen
For the border issue, you might want to check out what the OP of this question did (linking here because the related documentation is also inked)
EDIT2
Changed the above code so that the rectangle can be visible when the Border is large enough (you can still refer to the linked question for the border issue)

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

Absolute positioning of a panel defined in a content control

I am trying to write a custom control in Windows UWP by inheriting from a Control class (A button with custom action). On clicking of this button I want to show a panel at the bottom of the page irrespective of where the control is being used in the page (Kind of a popup but I need the freedom in defining the position of the panel on the screen).
Can anyone help how i can get this done in XAML. Below is the template I am using for my custom control.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UI.Controls"
xmlns:converters="using:UI.ValueConverters">
<Style TargetType="local:Plugin">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:Plugin">
<Grid>
<Grid.Resources>
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<x:Double x:Key="EllipseDimension">30</x:Double>
</Grid.Resources>
<Button Name="PluginButton"
Width="{TemplateBinding PluginWidth}"
Height="{TemplateBinding PluginHeight}"
Command="{Binding PluginTrigger}"
Padding="0"
VerticalAlignment="Top"
AutomationProperties.Name="Main button"
Background="Transparent"
BorderThickness="0"
TabIndex="0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<SymbolIcon Symbol="{TemplateBinding Symbol}"
Visibility="{Binding Image, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=true}"
Foreground="Black"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ToolTipService.ToolTip="{TemplateBinding Label}" />
<Ellipse Visibility="{Binding Image, Converter={StaticResource NullToVisibilityConverter}}"
Width="{StaticResource EllipseDimension}"
Height="{StaticResource EllipseDimension}">
<Ellipse.Fill>
<ImageBrush ImageSource="{Binding Image}" />
</Ellipse.Fill>
</Ellipse>
</Grid>
</Button>
<StackPanel Name="popuptoshow"></StackPanel>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

Applying border style on certain grid cells in WPF

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:

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>

Window Style and using controls (C# and WPF)

I'm using Visual Studio 2013 to create my applications. I started to learn programming 4 years ago, and now a days I wanna to improve my programmer experience.
In the last days I had to create a simply application, but I didn't want to use a default style of a window. So I read that I could create a style for my window. I did it, it works fine, but there's a little problem: I can't put anything inside my window now... All the controls I put into a grid, into the window tag, aren't visible, but the compiler doesn't show any problems.
Here is the Style Code, then my Window XAML
<Style TargetType="Window" x:Key="DefaultWindow">
<Setter Property="AllowsTransparency" Value="True"/>
<Setter Property="WindowStyle" Value="None"/>
<Setter Property="ResizeMode" Value="CanResizeWithGrip"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderThickness="1" BorderBrush="Black">
<Border BorderThickness="3" BorderBrush="#FF244E97">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#FF244E97">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0" Grid.Row="0" Stretch="Uniform" HorizontalAlignment="Left" Margin="10">
<TextBlock FontFamily="Corbel" Background="#FF244E97" Foreground="White">Costo Unitario</TextBlock>
</Viewbox>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Viewbox Grid.Column="0" Stretch="Uniform" HorizontalAlignment="Left" Margin="2, 10, 2, 10">
<TextBlock FontFamily="Corbel" Background="#FF244E97" Foreground="White">_</TextBlock>
</Viewbox>
<Viewbox Grid.Column="1" Stretch="Uniform" HorizontalAlignment="Left" Margin="2, 10, 2, 10">
<TextBlock FontFamily="Corbel" Background="#FF244E97" Foreground="White">◘</TextBlock>
</Viewbox>
<Viewbox Grid.Column="2" Stretch="Uniform" HorizontalAlignment="Left" Margin="2, 10, 20, 10">
<TextBlock FontFamily="Corbel" Background="#FF244E97" Foreground="White">X</TextBlock>
</Viewbox>
</Grid>
</Grid>
<Grid x:Name="ContenentGrid" Grid.Row="1" Background="White">
<ResizeGrip Width="10" Height="10" Grid.Column="1" VerticalAlignment="Bottom"/>
</Grid>
</Grid>
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And my Windows Xaml:
<Window x:Class="Pabich.Marcin._5HI.CostoUnitario.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chrt="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
Title="MainWindow" Height="600" Width="800" WindowStartupLocation="CenterScreen"
Style="{StaticResource DefaultWindow}">
<Grid>
<TextBlock>Hello!</TextBlock>
</Grid>
This should be a no-border window, within I can put controls, in the central grid. This is a screen of the window for now:
Screen of the Window
As you can see, I leaved all the white space for my controls, but they aren't there. So how can I make it?
PS: Keep in mind that I'm only a beginner, and I wanna to use simply code
I think that's happens because you don't use ContentPresenter to display window content. Without ContentPresenter WPF content model doesn't know where content should be placed and doesn't show it.
Try to add the ContentPresenter to your ContentGrid (WPF window also requires it in the AdornerDecorator).
<Grid x:Name="ContenentGrid" Grid.Row="1" Background="White">
<AdornerDecorator>
<ContentPresenter Content="{TemplateBinding Content}" />
</AdornerDecorator>
... ResizeGrip here ...
</Grid>

Categories

Resources