Очень краткий ответ: для этого вы используете Expression Blend.
Немного менее краткий ответ заключается в том, что большинство из того, что вы описываете, может быть выполнено путем редактирования шаблона элемента управления, если вы понимаете, как работают шаблоны элементов управления, и знаете, что редактировать. Expression Blend - хороший инструмент для этого, потому что Blend делает редактирование шаблона элемента управления относительно простым и потому, что Blend запоминает многое, что вы, вероятно, забудете, особенно если вы относительно новичок в WPF.
Например, если я зайду в Blend, нарисую кнопку на артборде и отредактирую копию ее шаблона управления, вот что я получаю, прежде чем даже начать что-то связывать:
<Style x:Key="ButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Stroke="Black" StrokeDashArray="1 2" StrokeThickness="1" Margin="2" SnapsToDevicePixels="true"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#F3F3F3" Offset="0"/>
<GradientStop Color="#EBEBEB" Offset="0.5"/>
<GradientStop Color="#DDDDDD" Offset="0.5"/>
<GradientStop Color="#CDCDCD" Offset="1"/>
</LinearGradientBrush>
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
<Style x:Key="ButtonControlTemplate" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" RenderDefaulted="{TemplateBinding IsDefaulted}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/>
</Microsoft_Windows_Themes:ButtonChrome>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="true">
<Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#ADADAD"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
В принципе, все, что вам нужно сделать, - это найти элемент ContentPresenter
(в который вставляется содержимое кнопки) и заменить то, что его окружает, своей изящной вещью. Вы можете скопировать этот XAML в свой собственный проект и поэкспериментировать с ним, и вы получите что-то вроде этого.
Но: есть много вещей, которые вам нужно понять, прежде чем вы в конечном итоге создадите кнопку, которая на самом деле делает то, что вы хотите. Большинство из них представляет собой функциональность и поведение, которые, если вы похожи на меня, когда у вас есть блестящая идея разработать собственную кнопку, не заставят себя задуматься. Как:
- Как должен измениться внешний вид кнопки, когда она имеет фокус?
- Как должен измениться внешний вид кнопки, когда она отключена?
- Какие события должны изменить внешний вид кнопки?
Если вы посмотрите на этот шаблон, вы заметите, что многие ответы на этот последний вопрос встроены в элемент Microsoft_Windows_Themes:ButtonChrome
. Все, что он делает в коде (например, RenderPressed
), это то, что вы должны встроить в свой XAML с помощью триггеров. (Или вы можете написать свой собственный объект, похожий на кнопку хрома.)
Полагаю, я говорю, что вы не на неправильном пути, но вам нужно многому научиться.
Что касается вашего второго вопроса, да, вы можете создать UserControl
, который предоставляет свойства для заголовка и изображения. Вы также можете немного поэкспериментировать с тем фактом, что кнопка фактически является элементом управления контентом, например ::
<Button Height=50>
<DockPanel>
<Image Width="32" Source="image.png"/>
<TextBlock Text="My button's caption" TextWrapping="Wrap" VerticalAlignment="Center"/>
</DockPanel>
</Button>