Форум программистов, компьютерный форум, киберфорум
Наши страницы
C#: WPF, UWP и Silverlight
Войти
Регистрация
Восстановить пароль
 
hamin
585 / 383 / 234
Регистрация: 21.11.2012
Сообщений: 1,163
1

ColorPicker WPF

16.07.2019, 15:48. Просмотров 942. Ответов 0
Метки нет (Все метки)

Лучший ответ Сообщение было отмечено Элд Хасп как решение

Решение

в данной теме хочу показать свою реализацию кастомного контрола ColorPicker для WPF. Может быть кому-то пригодится..

в моем последнем проекте у меня возникла необходимость выбора цвета и сохранение его как hex значение в базе данных. на первых парах я не придавал большого значения этому и выбирал цвет в сторонней программе, копировал вручную его hex значение и уже потом вставлял в программе и сохранял в бд. но когда я начал уже пользоваться написанной программой, я понял, что это очень неудобно, поэтому и захотел модифицировать программу. Конечно вариантов готовых решений очень много в интернете, но предпочитаю сделать все самому, тем более программка эта будет использоваться исключительно мной)

для начала нужно было определиться с элементами, которые я хочу видеть в выпадающем окошке.. мне нужны были след. пункты:
1. выбор цвета из стандартного набора цветов
2. выбор цвета из палитры
3. просмотр текущего цвета и его значение R,G,B и hex, а также настройка яркости

для реализации первой группы я выбрал ListBox. для него переопределил ItemsPanel и установил его в uniformgrid с 6 строками и 10 колонками:

Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<ListBox Grid.Row="1" Margin="0 5" x:Name="lbDefaultColors" Grid.ColumnSpan="4" SelectedIndex="0"
                                     SelectedItem="{Binding DefaultColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ColorPicker}}" 
                                     BorderThickness="0" Width="190"  ItemsSource="{TemplateBinding DefaultColors}" 
                                     ItemContainerStyle="{StaticResource ColorPickerItemStyle}">
                                        <ListBox.ItemsPanel>
                                            <ItemsPanelTemplate>
                                                <UniformGrid Rows="6" Columns="10"></UniformGrid>
                                            </ItemsPanelTemplate>
                                        </ListBox.ItemsPanel>
                                        <ListBox.ItemTemplate>
                                            <DataTemplate>
                                                <Border x:Name="br" Background="{Binding}" BorderBrush="#e4e4e4"/>
                                                <DataTemplate.Triggers>
                                                    <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=ListBoxItem}}" Value="true">
                                                        <Setter TargetName="br" Value="1" Property="BorderThickness"></Setter>
                                                    </DataTrigger>
                                                </DataTemplate.Triggers>
                                            </DataTemplate>
                                        </ListBox.ItemTemplate>
                                    </ListBox>


коллекция стандартных цветов задается у меня в коде, ее я перенял из экселя)

Кликните здесь для просмотра всего текста
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
internal ObservableCollection<Brush> DefaultColors
        {
            get { return (ObservableCollection<Brush>)GetValue(DefaultColorsProperty); }
            set { SetValue(DefaultColorsProperty, value); }
        }
 
        internal static readonly DependencyProperty DefaultColorsProperty =
            DependencyProperty.Register("DefaultColors", typeof(ObservableCollection<Brush>), typeof(ColorPicker), new PropertyMetadata(GetDefaultColors()));
 
 
        private static ObservableCollection<Brush> GetDefaultColors()
        {
            var result = new ObservableCollection<Brush>();
            result.Add(Color.FromRgb(255, 255, 255).ToBrush());
            result.Add(Color.FromRgb(0, 0, 0).ToBrush());
            result.Add(Color.FromRgb(231, 230, 230).ToBrush()); 
            //.. и т.д., всего 60 цветов
        }
 
//Также добавил функцию расширений для конвертации цвета в кисть:
public static class ColorExtensions
    {
        public static Brush ToBrush(this Color color)
        {
            return new SolidColorBrush(color);
        }
    }


здесь все достаточно элементарно с помощью выбора текущего айтема в листбоксе

2. для выбора цвета из палитры во многих реализациях берется уже готовая картинка и по информации из пикселя, куда пользователь тыкает мышкой, выбирается цвет.. сделал немного по-другому, немного проще. я сгенерировал коллекцию значений цветов исходя из моей палитры:
Сама палитра в xamle

Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
<Border Height="15" Margin="5 5 0 0" BorderBrush="Silver" BorderThickness="1">
    <Border.Background>
         <LinearGradientBrush StartPoint="0,1" EndPoint="1,1" x:Name="lgb">
               <GradientStop Color="#ff0000" Offset="0"></GradientStop>
               <GradientStop Color="#ffff00" Offset="0.2"></GradientStop>
               <GradientStop Color="#00ff00" Offset="0.31"></GradientStop>
               <GradientStop Color="#00ffff" Offset="0.46"></GradientStop>
               <GradientStop Color="#0000ff" Offset="0.60"></GradientStop>
               <GradientStop Color="#ff00ff" Offset="0.8"></GradientStop>
               <GradientStop Color="#ff0000" Offset="1"></GradientStop>
        </LinearGradientBrush>
   </Border.Background>
</Border>


далее генерация цветов в коде:
Кликните здесь для просмотра всего текста
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
        private static List<Tuple<int, int, int>> GetUserCustomColors()
        {
            var list = new List<Tuple<int, int, int>>();
            var max = 255;
            var min = 0;
 
 
            //#ff0000 -> #ffff00
            for (int i = 0; i <= 255; i++)
            {
                list.Add(Tuple.Create(max, i, min));
            }
 
            //#ffff00 -> #00ff00
            for (int i = 255; i >= 0; i--)
            {
                list.Add(Tuple.Create(i, max, min));
            }
 
            //#00ff00 -> #00ffff
            for (int i = 0; i <= 255; i++)
            {
                list.Add(Tuple.Create(min, max, i));
            }
           
            //и.т.д, всего 6 циклов
       }


эту палитру я поместил в стиль слайдера. В коллекции генерируются 1536 цветов, поэтому мой слайдер выглядит так:

Кликните здесь для просмотра всего текста
XML
1
2
3
4
<Slider Grid.Row="3" Minimum="0" Maximum="1535" 
                                    Value="{Binding UserCustomValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ColorPicker}}" 
                                    Style="{StaticResource ColorPickerSliderStyle}" Grid.ColumnSpan="2" Margin="0 5 5 5">
</Slider>


т.е. по сути текущее значение из слайдера это индекс цвета из листа.

3. предпросмотр текущего цвета и его значений - здесь, пожалуй, интересна только настройка яркости.. Яркость в данном контексте не совсем правильно,т.к. здесь я оперирую свойством alpha цвета, а этот параметр, насколько я знаю, отвечает за прозрачность. (поправьте, если я не прав).
для настройки яркости я сделал слайдер от 0 до 255 и его значение передавал для определения текущего цвета:

Кликните здесь для просмотра всего текста
XML
1
2
3
4
5
6
7
8
<Border Width="10" BorderBrush="Silver" BorderThickness="1" Margin="0 5 5 5">
    <Border.Background>
          <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
              <GradientStop Color="{Binding StartColor, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ColorPicker}}" Offset="0"></GradientStop>
                                            <GradientStop Color="{Binding EndColor, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:ColorPicker}}" Offset="1"></GradientStop>
                                        </LinearGradientBrush>
                                    </Border.Background>
                                </Border>


все эти элементы я перенес на окно popup и привязал его видимость:
Кликните здесь для просмотра всего текста
XML
1
2
3
4
<ToggleButton Grid.Column="1" Padding="2 1" Height="{TemplateBinding Height}" x:Name="tglColorPicker" Style="{StaticResource tglBtnColorPicker}">
 
                        </ToggleButton>
                        <Popup HorizontalOffset="10" StaysOpen="False" IsOpen="{Binding ElementName=tglColorPicker, Path=IsChecked, Mode=TwoWay}"/>


в итоге получился контрол, который полностью удовлетворяет моим потребностям по выбору цвета.

пример проекта приложил.
4
Изображения
 
Вложения
Тип файла: 7z TESTWPF.7z (33.3 Кб, 8 просмотров)
Лучшие ответы (1)
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.07.2019, 15:48
Ответы с готовыми решениями:

Вменяемый ColorPicker
Какой посоветуете? Только так чтобы не тянуть аж блин весь тулкит (типа этого недоплатного WPF...

Настройка цветов. Что-то вроде ColorPicker'a.
Здравстуйте. Хочу сделать подобную &quot;вещь&quot; как на картинке. Только не совсем понятно как заполнять...

WPF async void fun() для событий контролла. (MapCOntrol.WPF)
Задача: Отмечаем чекбокс элементы и рисуем их на карте. При нажатии на кнопку выполняется...

Открыть WPF внутри другого WPF окна
Добрый день! Имеется задача: В WPF окне (назовем его MainWindow.xaml с привязкой к...

Вызов окошка WPF из другого окна WPF
Всем доброго времени суток. Подскажите пожалуйста как мне вызвать из главного окна WPF другую. Я...

0
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.07.2019, 15:48

ColorDialog для WPF. Копии всякого старья для WPF
Последние три дня мучился в поисках ColorDialog для WPF. Не стороннего заменителя, а максимально...

Есть ли в WPF полноценная замена GDI+? Чтобы можно было всё, что можно в GDI+? Просто думаю углубляться в работу с изображениями в WPF или GDI.
Ну собственно весь вопрос в заголовке темы.

Нужен colorpicker
Мне нужен какой-то сolorpicker только не стандартный из AjaxToolKit.


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

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru