Controls
Button
Button is the standard action control in InkkSlinger. It is content-driven, raises a bubbling Click event, and executes commands through the shared control commanding pipeline.
Quick start
Use Content for ordinary caption buttons. A simple string is the default path, and you can move to richer content or a custom template without changing the control model later.
<Button Content="Save" Width="120" Height="36" />
Handle a click in XAML
<Button Content="Run import"
Width="140"
Height="40"
Click="OnRunImportClick" />
namespace InkkSlinger;
public partial class ImportView : UserControl
{
public ImportView()
{
InitializeComponent();
}
private void OnRunImportClick(object? sender, RoutedSimpleEventArgs args)
{
// Perform the action here.
}
}
Bind a command
<Button Content="Open"
Command="{Binding OpenCommand}"
CommandParameter="{Binding SelectedFile}" />
Default recommendation: start with string Content and either Click or Command. Move to richer content or a custom template only when the button needs a different visual tree.
Content and templating
InkkSlinger's Button is content-first. For ordinary buttons, set Content to a string. For richer visuals, provide a UI element or a template that presents the control's content.
String content
Use a string Content value for normal caption buttons. In the built-in render path, Button resolves that content to text and centers it inside the padded content area.
Rich content
Use UIElement content or a content-aware template when the button needs icons, stacked text, or a custom visual tree built around a ContentPresenter.
The current contract is:
- Plain, non-templated buttons render text resolved from
Contentwhen the content is a string or another text-like value. - Templates that include a
ContentPresenterdisplay the button'sContentdirectly. - If
Contentis already a UI element, Button hosts that visual content instead of generating an implicit text element. - If your template does not include a
ContentPresenter, the template controls what appears and Button does not force content into view.
<Style x:Key="CaptionButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Style="{StaticResource CaptionButtonStyle}" Content="Save" />
<Button Style="{StaticResource CaptionButtonStyle}" Content="Explicit content" />
Input and interaction
Button exposes the same action surface whether you drive it from pointer input, access keys, or commands. Visual states such as hover and pressed are available for styling and triggers.
Pointer states
IsMouseOver and IsPressed update during pointer interaction. Use them in styles or templates to change color, border, scale, or other visual properties.
Disabled state
IsEnabled="False" prevents activation. The built-in fallback style also changes the chrome so disabled buttons read differently from active ones.
Access keys
Button enables access-key recognition by default. An AccessText element can target the button by name and invoke it through an Alt-key gesture.
AccessText example
<StackPanel>
<AccessText Text="_Save" TargetName="SaveButton" />
<Button x:Name="SaveButton" Content="Save" />
</StackPanel>
Button also implements the shared command source contract inherited from Control:
Commandspecifies the action to execute.CommandParameterpasses extra data to the command.CommandTargetselects the target element when you do not want the default target resolution.- If the command reports
CanExecute == false, Button becomes disabled automatically until the command can execute again.
<Button Content="Open document"
Command="{StaticResource OpenCommand}"
CommandTarget="{Binding ElementName=EditorSurface}"
CommandParameter="{Binding SelectedDocument}" />
Styling and templating
Button is designed to be styled through normal dependency properties, implicit styles, and full templates. Most advanced visuals come from styles and template triggers rather than hard-coded control behavior.
Style the built-in chrome
<Button Content="Publish"
Background="#1F3B57"
Foreground="#F4FAFF"
BorderBrush="#3EA6FF"
BorderThickness="1"
Padding="16,8"
Width="160"
Height="42" />
Apply an implicit style to every Button
<Application.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#243140" />
<Setter Property="Foreground" Value="#F5FBFF" />
<Setter Property="BorderBrush" Value="#4FC7C1" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="14,8" />
</Style>
</Application.Resources>
Build a custom template
<Style x:Key="ActionButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="#2A2A2A" />
<Setter Property="Foreground" Value="#F0F0F0" />
<Setter Property="BorderBrush" Value="#3F3F3F" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="20,10" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="Chrome"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Chrome" Property="Background" Value="#333333" />
<Setter TargetName="Chrome" Property="BorderBrush" Value="#FF8C00" />
<Setter Property="Foreground" Value="#FFA940" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Chrome" Property="Background" Value="#1C1C1C" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Template bindings are the safest way to flow owner properties such as Background, BorderBrush, BorderThickness, and Padding into your custom visual tree.
Layout and text behavior
The non-templated Button path is intentionally simple. It draws button chrome, then centers the current text layout resolved from Content inside the inner content area after subtracting padding and border thickness.
PaddingandBorderThicknessboth contribute to desired size.TextWrappingcontrols whether plain text content stays on one line or wraps to the available width.- With
TextWrapping="NoWrap", Button prefers its intrinsic text width plus chrome. - With wrapped text, Button measures against the remaining inner width after padding and border are applied.
- If the resolved content text is empty, the button still occupies the space required by its padding and border.
<StackPanel Width="240">
<Button Content="Single line caption"
Margin="0,0,0,8" />
<Button Content="This caption is long enough to wrap when the available width is constrained."
TextWrapping="Wrap"
Padding="12,10" />
</StackPanel>
Properties and event reference
Content and action
Content: the button payload. Use a string for a standard caption or provide richer content for templated and composed visuals.
TextWrapping: controls whether plain text content is measured and rendered as a single line or wrapped lines.
Click: bubbling routed event raised when the button is invoked.
Command, CommandParameter, CommandTarget: inherited from Control and used for command execution.
Visuals and state
Background, Foreground, BorderBrush, BorderThickness, Padding: primary styling properties for built-in and templated visuals.
IsEnabled: inherited enable/disable state. Command gating can also drive this state.
IsMouseOver, IsPressed: interaction state properties commonly used by triggers.
Patterns and examples
Toolbar action button
<Button Content="Refresh"
Padding="10,6"
Margin="0,0,8,0"
Command="{Binding RefreshCommand}" />
Destructive action button style
<Style x:Key="DangerButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="#552222" />
<Setter Property="Foreground" Value="#FFF3F3" />
<Setter Property="BorderBrush" Value="#D05C5C" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Padding" Value="16,8" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#6A2626" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#441919" />
</Trigger>
</Style.Triggers>
</Style>
<Button Content="Delete save slot"
Style="{StaticResource DangerButtonStyle}" />
Icon and label in a custom template
<Style x:Key="IconButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="[icon]" Margin="0,0,8,0" />
<ContentPresenter VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Style="{StaticResource IconButtonStyle}"
Content="Featured"
Background="#223245"
BorderBrush="#4FC7C1"
BorderThickness="1"
Padding="14,8" />
Access-key driven command
<StackPanel>
<AccessText Text="_Open" TargetName="OpenButton" />
<Button x:Name="OpenButton"
Content="Open"
Command="{StaticResource OpenCommand}" />
</StackPanel>
Routed command example
<UserControl xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<RoutedUICommand x:Key="OpenCommand" Text="_Open" />
</UserControl.Resources>
<Grid>
<Button Content="Open"
Command="{StaticResource OpenCommand}" />
</Grid>
</UserControl>
Notes and pitfalls
Use string Content first. It is the simplest path for ordinary caption buttons and matches the built-in rendering path.
Templates need a ContentPresenter. If you expect button content to appear inside a template, the template must present that content itself.
Commands can disable the button automatically. If your command reports that it cannot execute, the button reflects that by becoming disabled until the command changes state.
Visual polish lives in styles. Hover, pressed, and animated effects are typically created with style and template triggers. Button does not ship with built-in animation behavior.