Форум программистов, компьютерный форум, киберфорум
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.86/64: Рейтинг темы: голосов - 64, средняя оценка - 4.86
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262

Кастомная кнопка в UserControl или UserControl со свойствами кнопки

01.09.2019, 19:54. Показов 16116. Ответов 128
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет,

пытаюсь запихнуть кастомную кнопку в Useк Control. Что-то ерунда какая-то получается.
Можете помочь?

Хотелось бы UC со свойствами кнопки. Чтобы при клике меняла цвет своего Fill. и чтобы handle event был и binding работал, Также, от прилетаещего bool меняла свой Fill.

Спасибо!

XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<UserControl x:Class="Button_testing.UserControls.Polygon_Button"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Button_testing.UserControls"
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="100">
    <Grid>
 
 
       
        <Button Name="button1" Height="90" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="90"
     Content="No content">
 
            <Button.Template>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Grid Margin="5">
                        <Ellipse Stroke="DarkBlue" StrokeThickness="2">
                            <Ellipse.Fill>
                                <RadialGradientBrush Center="0.3,0.2" RadiusX="0.5" RadiusY="0.5">
                                    <GradientStop Color="Azure" Offset="0.1" />
                                    <GradientStop Color="CornflowerBlue" Offset="1.1" />
                                </RadialGradientBrush>
                            </Ellipse.Fill>
                        </Ellipse>
 
                        <ContentPresenter Name="content" HorizontalAlignment="Center" VerticalAlignment="Center"/>
 
                    </Grid>
                </ControlTemplate>
 
            </Button.Template>
        </Button>
 
    </Grid>
</UserControl>
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.09.2019, 19:54
Ответы с готовыми решениями:

Как разместить UserControl поверх другого UserControl
Такая задача. Есть форма. На ней размещена панель panelRight. Также есть два пользовательских контрола (TimelineControl() и Bar()). Потом в...

Не сохраняются значения свойств заданные в дизайнере после создания своего UserControl с дополнительными свойствами
using System.ComponentModel; using System.Windows.Forms; namespace Library { public partial class CellControl : UserControl ...

DP UserControl внутри UserControl MVVM
Есть UC c DP Text &lt;Grid&gt; &lt;TextBlock HorizontalAlignment=&quot;Left&quot; Text=&quot;{Binding Text, ElementName=UC}&quot;...

128
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
06.09.2019, 16:42
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Bulky Посмотреть сообщение
Я вообще из #26 взял версию. Там хотя бы все прозрачно, для меня.
Этот вариант работает через установку стиля внутри контрола.
Побочный баг - не принимает внешние стили.

То есть как я делаю в проверочном коде, единую стилизацию всех кнопок, с таким вариантом не прокатит. Придётся задавать для каждого экземпляра значения свойств.

XML
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.Resources>
            <local:BooleanToBrushConverter x:Key="BooleanToBrushConverter"
                    TrueBrush="Aquamarine" FalseBrush="Coral"/>
            <Style TargetType="{x:Type local:ButtonPolygon}">
                <Setter Property="Margin" Value="20"/>
                <Setter Property="Background" Value="Yellow"/>
                <Setter Property="DisabledBackground" Value="LightYellow"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="100"/>
                <Setter Property="StrokeThickness" Value="5"/>
                <Setter Property="IsEnabled" Value="{Binding IsChecked, ElementName=cbEnabled}"/>
                <Setter Property="PressedBackground" Value="{Binding IsChecked, ElementName=cbColor, Converter={StaticResource BooleanToBrushConverter}}"/>
            </Style>
        </Grid.Resources>
        <local:ButtonPolygon>
            <TextBlock TextAlignment="Center">
                Треугольная
                <LineBreak/>
                кнопка
            </TextBlock>
        </local:ButtonPolygon>
        <local:ButtonPolygon Grid.Column="1" 
                             InscribedPolygonDelegate="{x:Static local:InscribedPolygonClass.InscribedHexagonDelegate}">
            <TextBlock TextAlignment="Center">
                Шестиугольная
                <LineBreak/>
                кнопка
            </TextBlock>
        </local:ButtonPolygon>
        <local:ButtonPolygon Grid.Row="1" Grid.Column="1" PressedBackground="{Binding IsChecked, ElementName=cbColor, Converter={StaticResource BooleanToBrushConverter}}"
                             InscribedPolygonDelegate="{x:Static local:InscribedPolygonClass.InscribedMarkItemDelegate}">
            <TextBlock TextAlignment="Center">
                Кнопка
                <LineBreak/>
                галочка
            </TextBlock>
        </local:ButtonPolygon>
        
        <local:ButtonPolygon Grid.Row="1" Style="{x:Null}"
                             InscribedPolygonDelegate="{x:Static local:InscribedPolygonClass.InscribedRhombusDelegate}"
                             MouseOverBackground="Pink" PressedBackground="Red" Background="Green" DisabledBackground="LightGreen"
                             HorizontalContentAlignment="Center"
                             IsEnabled="{Binding IsChecked, ElementName=cbEnabled}">
            <TextBlock TextAlignment="Center">
                Ромбическая кнопка
                <LineBreak/>
                с отключенным
                <LineBreak/>
                стилем
            </TextBlock>
        </local:ButtonPolygon>
 
        <CheckBox x:Name="cbEnabled" Content="Включить кнопки" IsChecked="True" VerticalAlignment="Center" HorizontalAlignment="Center"
                  Grid.RowSpan="2" />
 
        <CheckBox x:Name="cbColor" IsChecked="{x:Null}" VerticalAlignment="Center" HorizontalAlignment="Center"
                  Grid.RowSpan="2" Grid.Column="1">
            <TextBlock>
                Изменить цвет
                <LineBreak/>
                PressedBackground
            </TextBlock>
 
        </CheckBox>
    </Grid>
Со строки 22 единый стиль для всех кнопок (в данном случае для треугольной, шестиугольной и галочки), но так с первоначальным вариантом контрола не выйдет.

Со строки 57 контрол с отключенным стилем и явным заданием всех свойств. Так придётся делать всегда.
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
06.09.2019, 16:45  [ТС]
Элд Хасп,

вы упоминали про костыль касательно верхнего stroke треугольника.
Ткните меня лицом в то место в коде пож.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
06.09.2019, 17:08
Цитата Сообщение от Ахромчон Посмотреть сообщение
вы упоминали про костыль касательно верхнего stroke треугольника.
C#
54
55
56
57
58
59
60
61
62
        /// <summary>Обработчик события изменения размера</summary>
        /// <param name="sender">Источник события - неиспользуется</param>
        /// <param name="e">Информация события</param>
        private void ButtonPolygon_SizeChanged(object sender, SizeChangedEventArgs e)
            => Points = new PointCollection
            (
                InscribedPolygonDelegate?.Invoke(e.NewSize.Width - StrokeThickness, e.NewSize.Height - StrokeThickness)
                .Select(pnt => new Point(pnt.X + StrokeThickness * 0.5, pnt.Y + StrokeThickness * 0.5))
            );
Передаём в метод размер контрола уменьшенный на ширину StrokeThickness, метод возвращает коллекцию вершин, создаётся новая коллекция вершин со смещёнными координатами на половину ширины StrokeThickness.

Мне не нравится, что приходится дважды создавать коллекцию вершин. Но как сделать проще не смог придумать.
1
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
06.09.2019, 22:24  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Мне не нравится, что приходится дважды создавать коллекцию вершин. Но как сделать проще не смог придумать.
После глубочайшего анализа, получил я симбиоз из двух v1 и v2, в том числе и улучшение верхнего stroke. И ухудшение в плане, не читает MS стили.


Вопрос: вот этот метод рисования довольно непрозрачен. Насколько метод продвинут и способен ли он несимметричные фигуры выдавать?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
06.09.2019, 22:47
Цитата Сообщение от Ахромчон Посмотреть сообщение
Насколько метод продвинут и способен ли он несимметричные фигуры выдавать?
Метод должен вернуть список вершин многоугольника вписанного в заданную область. Сколько вершин, их симметричность - роли не играет. Коллекция просто подставляется в элемент Polygon и он отрисовывает по ней многоугольник.

Добавлено через 1 минуту
Цитата Сообщение от Ахромчон Посмотреть сообщение
После глубочайшего анализа, получил я симбиоз из двух v1 и v2, в том числе и улучшение верхнего stroke. И ухудшение в плане, не читает MS стили.
Я так и не понял чем не устраивает последний мой вариант?
В нём вроде все баги исправлены. Всё работает как и задумывалось.
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
06.09.2019, 23:18  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Я так и не понял чем не устраивает последний мой вариант?
В нём вроде все баги исправлены. Всё работает как и задумывалось.
Ну мы же обсуждали. Стили из Win7 тянет в контрол.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
06.09.2019, 23:25
Цитата Сообщение от Ахромчон Посмотреть сообщение
Стили из Win7 тянет в контрол.
То есть вы вообще не собираетесь стили использовать? Свои, не дефолтные?
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
07.09.2019, 09:02  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
То есть вы вообще не собираетесь стили использовать? Свои, не дефолтные?
сорри, не стили, а темы. Где-то в #66, #76 обсуждали, затемнение на 2/3 кнопки. Сейчас верхний stroke is OK (ваша идея), темы не тащит из Win7.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
07.09.2019, 10:04
Цитата Сообщение от Ахромчон Посмотреть сообщение
сорри, не стили, а темы. Где-то в #66, #76 обсуждали, затемнение на 2/3 кнопки. Сейчас верхний stroke is OK (ваша идея), темы не тащит из Win7.
Это я понял.
Но с таким вариантом он, вообще, не принимает стили. Любые из темы OC или ваши собственные.
А стили это один из основных способов задания элементам.

По идее, у вас должен быть где-то словарь подключаемый в App с базовыми стилями для всех элементов чей внешний вид вы не хотите оставлять на откуп темам ОС.
А дополнительные стили создаются на их базе.

Из того что вы пишите, как я понял, вы просто не используете свои стили. Для одного-двух элементов это оправдано. Но для большего количества нет.
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
07.09.2019, 12:21  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Из того что вы пишите, как я понял, вы просто не используете свои стили. Для одного-двух элементов это оправдано. Но для большего количества нет.
Нужен просто минималистический control определенной формы c функционалом кнопки.
Если теоретически выразиться, скорее всего App, так сказать должно быть оторвано от всех стилей.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
07.09.2019, 13:13
Цитата Сообщение от Ахромчон Посмотреть сообщение
Нужен просто минималистический control определенной формы c функционалом кнопки.
В последнем варианте кнопки в конструкторе задайте нужные значения свойствам.
Эти значения можно будет задать только явно. Из стилей они подхватываться не будут.
Так же если нужна иная форма по умолчанию - поменяйте метод (строки 68-64) многоугольника установленный по умолчанию. Для примера изменён на треугольник с вершиной вправо
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
 
namespace ButtonTriangleWPF
{    /// <summary>Делегат функции возвращающей коллекцию вершин фигуры вписанной в заданную область</summary>
     /// <param name="width">Ширина области</param>
     /// <param name="height">Высота области</param>
     /// <returns>PointCollection - коллекцию вершин фигуры</returns>
    public delegate PointCollection InscribedPolygonHandler(double width, double height);
 
    /// <summary>
    /// Логика взаимодействия для ButtonTriangle.xaml
    /// Класс со свойствами дли многоугольной кнопки
    /// </summary>
    public partial class ButtonPolygon : Button
    {
        public ButtonPolygon()
        {
            /// Задание значение свойствам
            /// Эти свойства не будут связаны со внешним стилем
            Background = Brushes.LightPink;
            BorderBrush = Brushes.Pink;
 
            SizeChanged += ButtonPolygon_SizeChanged;
            InitializeComponent();
        }
 
        /// <summary>Статический конвертер в кисть</summary>
        static readonly BrushConverter brushConverter = new BrushConverter();
 
        /// <summary>Делегат функции возвращающей вершины многоугольника</summary>
        public InscribedPolygonHandler InscribedPolygonDelegate
        {
            get { return (InscribedPolygonHandler)GetValue(InscribedPolygonDelegateProperty); }
            set { SetValue(InscribedPolygonDelegateProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for InscribedPolygonDelegate.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty InscribedPolygonDelegateProperty =
            DependencyProperty.Register("InscribedPolygonDelegate", typeof(InscribedPolygonHandler), typeof(ButtonPolygon), new PropertyMetadata((InscribedPolygonHandler)InscribedTriangleMetod));
 
 
        protected static readonly DependencyPropertyKey PointsKey =
            DependencyProperty.RegisterReadOnly(nameof(Points), typeof(PointCollection), typeof(ButtonPolygon), new PropertyMetadata(null));
 
        /// <summary>Свойство только для чтения. 
        /// Возвращает коллекцию вершин</summary>
        public PointCollection Points
        {
            get { return (PointCollection)GetValue(PointsProperty); }
            protected set { SetValue(PointsKey, value); }
        }
 
        // Using a DependencyProperty as the backing store for Points.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PointsProperty = PointsKey.DependencyProperty;
 
        /// <summary>Обработчик события изменения размера</summary>
        /// <param name="sender">Источник события - не используется</param>
        /// <param name="e">Информация события</param>
        private void ButtonPolygon_SizeChanged(object sender, SizeChangedEventArgs e)
            => Points = new PointCollection
            (
                InscribedPolygonDelegate?.Invoke(e.NewSize.Width - StrokeThickness, e.NewSize.Height - StrokeThickness)
                .Select(pnt => new Point(pnt.X + StrokeThickness * 0.5, pnt.Y + StrokeThickness * 0.5)));
 
        /// <summary>Делегат многоугольника по умолчанию.
        /// Возвращает вершины вписанного треугольника</summary>
        /// <param name="width">Ширина выделенной области</param>
        /// <param name="height">Высота выделенной области</param>
        /// <returns>PointCollection с вершинами треугольника</returns>
        static protected PointCollection InscribedTriangleMetod(double width, double height)
            => new PointCollection() { new Point(0, 0), new Point(0, height), new Point(width, 0.5 * height) };
 
 
        /// <summary>Кисть фона при наведении курсора мыши</summary>
        public Brush MouseOverBackground
        {
            get { return (Brush)GetValue(MouseOverBackgroundProperty); }
            set { SetValue(MouseOverBackgroundProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for MouseOverBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MouseOverBackgroundProperty =
            DependencyProperty.Register(nameof(MouseOverBackground), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FFBEE6FD")));
 
 
 
        /// <summary>Кисть границы при наведении курсора мыши</summary>
        public Brush MouseOverBorder
        {
            get { return (Brush)GetValue(MouseOverBorderProperty); }
            set { SetValue(MouseOverBorderProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for MouseOverBorder.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty MouseOverBorderProperty =
            DependencyProperty.Register(nameof(MouseOverBorder), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FF3C7FB1")));
 
 
 
        /// <summary>Кисть фона нажатой кнопки</summary>
        public Brush PressedBackground
        {
            get { return (Brush)GetValue(PressedBackgroundProperty); }
            set { SetValue(PressedBackgroundProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for PressedBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PressedBackgroundProperty =
            DependencyProperty.Register(nameof(PressedBackground), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FFC4E5F6")));
 
 
 
        /// <summary>Кисть границы нажатой кнопки</summary>
        public Brush PressedBorder
        {
            get { return (Brush)GetValue(PressedBorderProperty); }
            set { SetValue(PressedBorderProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for PressedBorder.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PressedBorderProperty =
            DependencyProperty.Register(nameof(PressedBorder), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FF2C628B")));
 
 
 
        /// <summary>Кисть фона отключенной кнопки</summary>
        public Brush DisabledBackground
        {
            get { return (Brush)GetValue(DisabledBackgroundProperty); }
            set { SetValue(DisabledBackgroundProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for DisabledBackground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisabledBackgroundProperty =
            DependencyProperty.Register(nameof(DisabledBackground), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FFF4F4F4")));
 
 
 
 
        /// <summary>Кисть границы отключенной кнопки</summary>
        public Brush DisabledBorder
        {
            get { return (Brush)GetValue(DisabledBorderProperty); }
            set { SetValue(DisabledBorderProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for DisabledBorder.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisabledBorderProperty =
            DependencyProperty.Register(nameof(DisabledBorder), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FFADB2B5")));
 
 
 
        /// <summary>Кисть текста отключенной кнопки</summary>
        public Brush DisabledForeground
        {
            get { return (Brush)GetValue(DisabledForegroundProperty); }
            set { SetValue(DisabledForegroundProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for DisabledForeground.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DisabledForegroundProperty =
            DependencyProperty.Register(nameof(DisabledForeground), typeof(Brush), typeof(ButtonPolygon), new PropertyMetadata(brushConverter.ConvertFrom("#FF838383")));
 
 
 
        /// <summary>Ширина границы многоугольника</summary>
        public double StrokeThickness
        {
            get { return (double)GetValue(StrokeThicknessProperty); }
            set { SetValue(StrokeThicknessProperty, value); }
        }
 
        // Using a DependencyProperty as the backing store for StrokeThickness.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StrokeThicknessProperty =
            DependencyProperty.Register(nameof(StrokeThickness), typeof(double), typeof(ButtonPolygon), new PropertyMetadata(1.0));
 
 
    }
}
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<Button x:Name="PART_ButtonDP" x:Class="ButtonTriangleWPF.ButtonPolygon" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:local="clr-namespace:ButtonTriangleWPF"
        mc:Ignorable="d" 
        d:DesignHeight="450" d:DesignWidth="800">
    <Button.Resources>
        <Style TargetType="local:ButtonPolygon" x:Key="DefaultStyle.ButtonPolygon">
            <Setter Property="Background" Value="LightBlue"/>
        </Style>
    </Button.Resources>
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Grid SnapsToDevicePixels="true">
                <Polygon x:Name="PART_Polygon" 
                         Points="{Binding Points, ElementName=PART_ButtonDP}" 
                         StrokeThickness="{Binding StrokeThickness, ElementName=PART_ButtonDP}" 
                         Stroke="{TemplateBinding BorderBrush}"
                         Fill="{TemplateBinding Background}"/>
                <ContentPresenter x:Name="contentPresenter"
                                  Focusable="False"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                  Margin="{TemplateBinding Padding}" 
                                  RecognizesAccessKey="True" 
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsDefaulted" Value="true">
                    <Setter Property="Stroke" TargetName="PART_Polygon" 
                            Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Fill" TargetName="PART_Polygon" 
                            Value="{Binding MouseOverBackground, ElementName=PART_ButtonDP}"/>
                    <Setter Property="Stroke" TargetName="PART_Polygon"
                            Value="{Binding MouseOverBorder, ElementName=PART_ButtonDP}"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="true">
                    <Setter Property="Fill" TargetName="PART_Polygon"
                            Value="{Binding PressedBackground, ElementName=PART_ButtonDP}"/>
                    <Setter Property="Stroke" TargetName="PART_Polygon"
                            Value="{Binding PressedBorder, ElementName=PART_ButtonDP}"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Fill" TargetName="PART_Polygon"
                            Value="{Binding DisabledBackground, ElementName=PART_ButtonDP}"/>
                    <Setter Property="Stroke" TargetName="PART_Polygon"
                            Value="{Binding DisabledBorder, ElementName=PART_ButtonDP}"/>
                    <Setter Property="TextElement.Foreground"
                            TargetName="contentPresenter" Value="{Binding DisabledForeground, ElementName=PART_ButtonDP}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>
XAML окна для проверки
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<Window x:Class="ButtonTriangleWPF.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:ButtonTriangleWPF"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="400">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.Resources>
            <local:BooleanToBrushConverter x:Key="BooleanToBrushConverter"
                    TrueBrush="Aquamarine" FalseBrush="Coral"/>
            <Style TargetType="{x:Type local:ButtonPolygon}">
                <Setter Property="Margin" Value="20"/>
                <Setter Property="Background" Value="Yellow"/>
                <Setter Property="DisabledBackground" Value="LightYellow"/>
                <Setter Property="Width" Value="100"/>
                <Setter Property="Height" Value="100"/>
                <Setter Property="StrokeThickness" Value="5"/>
                <Setter Property="IsEnabled" Value="{Binding IsChecked, ElementName=cbEnabled}"/>
                <Setter Property="PressedBackground" Value="{Binding IsChecked, ElementName=cbColor, Converter={StaticResource BooleanToBrushConverter}}"/>
            </Style>
        </Grid.Resources>
        <local:ButtonPolygon>
            <TextBlock TextAlignment="Center">
                Треугольная
                <LineBreak/>
                кнопка
            </TextBlock>
        </local:ButtonPolygon>
        <local:ButtonPolygon Grid.Column="1" 
                             InscribedPolygonDelegate="{x:Static local:InscribedPolygonClass.InscribedHexagonDelegate}">
            <TextBlock TextAlignment="Center">
                Шестиугольная
                <LineBreak/>
                кнопка
            </TextBlock>
        </local:ButtonPolygon>
        <local:ButtonPolygon Grid.Row="1" Grid.Column="1" PressedBackground="{Binding IsChecked, ElementName=cbColor, Converter={StaticResource BooleanToBrushConverter}}"
                             InscribedPolygonDelegate="{x:Static local:InscribedPolygonClass.InscribedMarkItemDelegate}">
            <TextBlock TextAlignment="Center">
                Кнопка
                <LineBreak/>
                галочка
            </TextBlock>
        </local:ButtonPolygon>
        
        <local:ButtonPolygon Grid.Row="1" Style="{x:Null}"
                             InscribedPolygonDelegate="{x:Static local:InscribedPolygonClass.InscribedRhombusDelegate}"
                             MouseOverBackground="Pink" PressedBackground="Red" Background="Green" DisabledBackground="LightGreen"
                             HorizontalContentAlignment="Center" StrokeThickness="10" BorderBrush="LightGreen"
                             IsEnabled="{Binding IsChecked, ElementName=cbEnabled}">
            <TextBlock TextAlignment="Center">
                Ромбическая кнопка
                <LineBreak/>
                с отключенным
                <LineBreak/>
                стилем
            </TextBlock>
        </local:ButtonPolygon>
 
        <CheckBox x:Name="cbEnabled" Content="Включить кнопки" IsChecked="True" VerticalAlignment="Center" HorizontalAlignment="Center"
                  Grid.RowSpan="2" />
 
        <CheckBox x:Name="cbColor" IsChecked="{x:Null}" VerticalAlignment="Center" HorizontalAlignment="Center"
                  Grid.RowSpan="2" Grid.Column="1">
            <TextBlock>
                Изменить цвет
                <LineBreak/>
                PressedBackground
            </TextBlock>
 
        </CheckBox>
    </Grid>
</Window>

Как видно в примере свойства Background и BorderBrush перестали принимать значения из стиля. В примере в стиле фону задан жёлтый цвет. Их можно задать только явно, как ромбо-кнопке.

Добавлено через 3 минуты
Цитата Сообщение от Ахромчон Посмотреть сообщение
Если теоретически выразиться, скорее всего App, так сказать должно быть оторвано от всех стилей.
Для этого в App подключается словарь со своей темой.
Это лучше чем "жёсткое" задание значений в самом UC.
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
07.09.2019, 14:38  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Для этого в App подключается словарь со своей темой.
Это лучше чем "жёсткое" задание значений в самом UC.
Конечно вы правы,
т.к. App базируется на махаппе, словарь, точнее словари уже есть. Но некоторые UC должны иметь свой 'окрас'.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
07.09.2019, 16:30
Цитата Сообщение от Ахромчон Посмотреть сообщение
Но некоторые UC должны иметь свой 'окрас'.
Это задаётся в стилях расположенных ближе к элементу, в том числе в самые близкие - в ресурсах самого элемента, его контейнера, окна.
Если один и тот же внешний вид требуется двум элементам, то уже стоит задуматься об общем для них стиле, если трём и больше, то уже точно следует сделать для них единый стиль.

Чаще всего у меня XAML с контейнером кнопок выглядит подобным образом
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        <StackPanel>
            <StackPanel.Resources>
                <Style TargetType="Button" BasedOn="{StaticResource Button.Style.Base}">
                    <Setter Property="Command" Value="{Binding ButtonCommand}"/>
                    <Setter Property="CommandParameter" Value="{Binding Content, RelativeSource={RelativeSource Self}}"/>
                    <Setter Property="ContentTemplate" Value="{StaticResource DataTemplate.ButtonConten}"/>
                    <!--Дальше значения для других свойств-->
                </Style>
            </StackPanel.Resources>
            <Button>
                <local:ButtonDate Name="Сохранить" Action="Save"/>
            </Button>
            <Button>
                <local:ButtonDate Name="Удалить" Action="Delete"/>
            </Button>
            <Button>
                <local:ButtonDate Name="Сохранить как" Action="SaveAs"/>
            </Button>
        </StackPanel>
Если без шаблона данных, то можно так
XML
1
2
3
4
5
6
7
8
9
10
11
12
        <StackPanel>
            <StackPanel.Resources>
                <Style TargetType="Button" BasedOn="{StaticResource Button.Style.Base}">
                    <Setter Property="Command" Value="{Binding ButtonCommand}"/>
                    <Setter Property="CommandParameter" Value="{Binding Content, RelativeSource={RelativeSource Self}}"/>
                    <!--Дальше значения для других свойств-->
                </Style>
            </StackPanel.Resources>
            <Button Content="Сохранить" />
            <Button Content="Сохранить как" />
            <Button Content="Удалить" />
        </StackPanel>
Если стиль большой, то переношу его в словарь, а в контейнере просто делаю ссылку на него
XML
1
2
3
4
5
6
7
8
        <StackPanel>
            <StackPanel.Resources>
                <Style TargetType="Button" BasedOn="{StaticResource Button.Style.FileAction}"/>
            </StackPanel.Resources>
            <Button Content="Сохранить" />
            <Button Content="Сохранить как" />
            <Button Content="Удалить" />
        </StackPanel>
Всё получается единообразно.
Если надо поменять внешний вид, то меняешь в одном месте, но единообразие сохраняется.

Поэтому для меня - применение стиля для элемента очень важно. Да, я думаю и для большинства реальных программистов.
1
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
08.09.2019, 20:33  [ТС]
В тему кнопки,

В XAML можно написать,

XML
1
<Button   x:Name="Button1"  Click="Button1"  ClickMode="Press"/>
И в .cs файле создается event handler button1_click. Срабатывающий на Press.

Следующий event handler этой же кнопки мне нужен на Release.

Как получить его для этой же кнопки? Два ClickMode в одной кнопке, -XAML не позволяет.
0
08.09.2019, 23:07
 Комментарий модератора 
Цитата Сообщение от Ахромчон Посмотреть сообщение
В тему кнопки,
Тема разрослась и уходит в сторону.
Поэтому предыдущий пост копирую в новую тему Два ClickMode на один элемент.
И дальше обсуждение двух ClickMode будет там.
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
08.09.2019, 23:13  [ТС]
ОК, категорически согласен!
0
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
13.09.2019, 16:19  [ТС]
Добрый день. А каким образом отключить у кнопки всяческие MouseOver реакции?
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
13.09.2019, 17:07
Цитата Сообщение от Ахромчон Посмотреть сообщение
А каким образом отключить у кнопки всяческие MouseOver реакции?
Или триггера в кнопке убрать. Это в самом UC.
Или задать цвета для MouseOver равными цветам обычного состояния. Это в стиле контрола в окне где будет использоваться UC.
1
21 / 17 / 1
Регистрация: 01.09.2019
Сообщений: 262
13.09.2019, 17:56  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Или триггера в кнопке убрать. Это в самом UC.
Или задать цвета для MouseOver равными цветам обычного состояния. Это в стиле контрола в окне где будет использоваться UC.
-цвета равными пробовал, -не вариант.
Что написал-то, триггер хотел убрать, но недалеко. Думал в теле триггрера есть настройка типа enabled-disabled. Триггер закмомментировал, -вариант.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16165 / 11285 / 2891
Регистрация: 21.04.2018
Сообщений: 33,173
Записей в блоге: 2
13.09.2019, 18:30
Цитата Сообщение от Ахромчон Посмотреть сообщение
-цвета равными пробовал, -не вариант.
Что написал-то, триггер хотел убрать, но недалеко. Думал в теле триггрера есть настройка типа enabled-disabled. Триггер закмомментировал, -вариант.
Я не знаю какой из вариантов вы используете. Вариант в котором нормально работает стиль вот этот
Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<Button x:Name="PART_ButtonDP" x:Class="Triangle_btn_Mahapps_based.UControls.ButtonPolygon" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
        xmlns:local="clr-namespace:Triangle_btn_Mahapps_based.UControls"
        mc:Ignorable="d" 
        d:DesignHeight="450" d:DesignWidth="800">
    <Button.Resources>
        <Style TargetType="local:ButtonPolygon" x:Key="DefaultStyle.ButtonPolygon">
            <Setter Property="Background" Value="LightBlue"/>
        </Style>
    </Button.Resources>
    <Button.Template>
        <ControlTemplate TargetType="{x:Type Button}">
            <Grid SnapsToDevicePixels="true">
                <Polygon x:Name="PART_Polygon" 
                         Points="{Binding Points, ElementName=PART_ButtonDP}" 
                         StrokeThickness="{Binding StrokeThickness, ElementName=PART_ButtonDP}" 
                         Stroke="{TemplateBinding BorderBrush}"
                         Fill="{TemplateBinding Background}"/>
                <ContentPresenter x:Name="contentPresenter"
                                  Focusable="False"
                                  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                  Margin="{TemplateBinding Padding}" 
                                  RecognizesAccessKey="True" 
                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsDefaulted" Value="true">
                    <Setter Property="Stroke" TargetName="PART_Polygon" 
                            Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="Fill" TargetName="PART_Polygon" 
                            Value="{Binding MouseOverBackground, ElementName=PART_ButtonDP}"/>
                    <Setter Property="Stroke" TargetName="PART_Polygon"
                            Value="{Binding MouseOverBorder, ElementName=PART_ButtonDP}"/>
                </Trigger>
                <Trigger Property="IsPressed" Value="true">
                    <Setter Property="Fill" TargetName="PART_Polygon"
                            Value="{Binding PressedBackground, ElementName=PART_ButtonDP}"/>
                    <Setter Property="Stroke" TargetName="PART_Polygon"
                            Value="{Binding PressedBorder, ElementName=PART_ButtonDP}"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Fill" TargetName="PART_Polygon"
                            Value="{Binding DisabledBackground, ElementName=PART_ButtonDP}"/>
                    <Setter Property="Stroke" TargetName="PART_Polygon"
                            Value="{Binding DisabledBorder, ElementName=PART_ButtonDP}"/>
                    <Setter Property="TextElement.Foreground"
                            TargetName="contentPresenter" Value="{Binding DisabledForeground, ElementName=PART_ButtonDP}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>


Для этого варианта в свойствах одной кнопки можно сделать так
XML
1
2
3
4
5
6
        <UControls:ButtonPolygon
            Margin="30"
            Content="ButtonPolygon - новый вариант"
            MouseOverBackground="{Binding Background, RelativeSource={RelativeSource Self}}"
            MouseOverBorder="{Binding BorderBrush, RelativeSource={RelativeSource Self}}" 
            />
А для всех кнопок в одно контейнере так
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.Resources>
            <Style TargetType="{x:Type UControls:ButtonPolygon}">
                <Setter Property="MouseOverBackground" Value="{Binding Background, RelativeSource={RelativeSource Self}}"/>
                <Setter Property="MouseOverBorder" Value="{Binding BorderBrush, RelativeSource={RelativeSource Self}}"/>
                <Setter Property="Margin" Value="30"/>
            </Style>
        </Grid.Resources>
        <UControls:ButtonPolygon Content="Верхняя кнопка"/>
        <UControls:ButtonPolygon Grid.Row="1" Content="Нижняя кнопка"/>
    </Grid>
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.09.2019, 18:30

Управление usercontrol из другого usercontrol
На форме размещено 2 usercontrol. Как управлять usercontrol из другого Добавлено через 22 часа 33 минуты Что не кто не поможет?

Вызов свойства кнопки на другом UserControl.xaml.cs
Возник вопрос получения свойства кнопки true на другом UserControl.xaml.cs. На первом UserControl1.xaml.cs кнопка определена как...

Биндинг или DataContext для UserControl
У меня есть простенький UserControl: &lt;UserControl x:Class=&quot;SimpleMVVM.ViewModel.LibraryViewModel&quot; ...

WPF MVVM View и ViewModel или UserControl и DependencyProperty
Не так давно ударился в WPF и шаблон MVVM. Вот такой вопрос возник... У меня есть View которая &quot;собирается&quot; из более мелких View....

Можно ли рисовать сразу на UserControl без Canvas или Grid
Можно ли в SilverLight рисовать сразу на UserControl без Canvas или Grid?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
100
Ответ Создать тему
Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru