Очень люблю, когда на кнопках есть цветные иконки, позволяющие мгновенно понимать назначение (это у меня ещё со времён Delphi повелось).
Но т.к. гемороиться с картинками неохота, использую бесплатный
Awesome Font (версии 5).
Соотв. кнопка состоит из TextBlock для иконки и TextBlock для текста. Самые часто нужные проперти вынул на верхний уровень.
Получился вот такой говнокодик:
| Незамутнённый C# код |
| public class AwesomeButton : Button
{
public TextBlock txtCaption;
public TextBlock txtIcon;
public AwesomeButton ()
{
#region create Button content manually
txtCaption = new TextBlock {
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
};
txtIcon = new TextBlock {
Text = "\uF005",// star
FontFamily = new FontFamily("Font Awesome 5 Free Regular"),
FontSize = 16,
Padding = new Thickness(5, 2, 5, 2),
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
};
txtIcon.SetValue(TextOptions.TextFormattingModeProperty, TextFormattingMode.Ideal);
var dock = new DockPanel();
DockPanel.SetDock(txtIcon, IconPos);
dock.Children.Add(txtIcon);
dock.Children.Add(txtCaption);
var grid = new Grid();// needed only to be sure 'dock' is shrinked to all avl space
grid.Children.Add(dock);
this.Content = grid;
#endregion
}
/// <summary>String of characters from 'Awesome' font</summary>
public string IconText
{
get => txtIcon.Text;
set => txtIcon.Text = value;
}
Dock _iconPos = Dock.Left;
public Dock IconPos
{
get => _iconPos;
set {
_iconPos = value;
DockPanel.SetDock(txtIcon, _iconPos);
}
}
public Brush IconColor
{
get => txtIcon.Foreground;
set => txtIcon.Foreground = value;
}
public double IconSize
{
get => txtIcon.FontSize;
set => txtIcon.FontSize = value;
}
/// <summary>Text appearing on the button</summary>
public string Text
{
get => txtCaption.Text;
set => txtCaption.Text = value;
}
public new bool IsEnabled
{
get => base.IsEnabled;
set {
base.IsEnabled = value;
txtIcon.Opacity = (value ? 1.0 : 0.5);// icon is not affected by IsEnabled - make disabled look manually
}
}
}
|
| |
Если выставлять IconPos, можно регулировать, где иконка появится — на всех 4 сторонах света. Обратите внимание ещё на txtCaption и txtIcon — это как раз "выставленные наружу" наши текстбоксы, позволяющие в коде
регулировать то, что не видно в WPF. К слову, почему-то нельзя написать в XAML
<AwesomeButton txtCaption.FontSize="100" />
Если подскажете ПОЧЕМУ, буду очень рад. (сейчас это поля, но даже когда они были пропертями, всё равно XAML не позволял такой финт) Ну а работающий вариант такой:
<cmn:AwesomeButton IconPos="Left" Click="btnRefresh_Click" Text="Refresh" IconText="" IconSize="18" IconColor="DodgerBlue" Padding="3" />
Да, ещё вопрос: нужно ли к этому классу писать что-то вроде
static AwesomeButton()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(AwesomeButton), new FrameworkPropertyMetadata(typeof(AwesomeButton)));
}
Или WPF'у достаточно того, что класс и так напрямую унаследован он Button?
Публикую затем, что в WPF такого нет и не будет
— может кому пригодится, чтобы самим не гемороиться. Ну и цель №2 — критика.
Прежде, чем вы закидаете говном мою кнопыську, сразу напишу в оправдание: я не особый спец по WPF, юзаю в осн. готовые контролы, а процесс создания кнопки с нуля — это полный мрак! (спасибо MS)
Соотв. я решил задачу максимально простым методом — тупо унаследовал класс и добавил пропертей. Это я к тому, что этот путь тоже оправдан — люди, которые не особо углублялись в WPF, вполне смогут улучшать мой код.
Короче, прошу не столько возгласов "да тут шаблоны надо было на 3 километра написать!", сколько рациональных улучшений именно для моего варианта контрола. Понятно, что кое-что нахардкодил, но это невелик грех, интересны остальные аспекты.
Всем заранее спасибо!