WPF ColorPicker 和 BrushEditor





5.00/5 (10投票s)
类似于 KAXAML 的。
介绍
嗯,我仍然没有找到一个完美的 WPF ColorPicker 控件来在我的项目中使用。有一些不错的控件,但我最喜欢的是 KAXAML 的,所以,我想我可能会尝试复制它。
背景
该项目大致上是 MVVM,包含两个用户控件,ColorEditor
和 BrushEditor
,并且为了您的方便,它们被打包在一个单独的类库项目中。
我遇到的第一个障碍是尝试生成 ColorPicker 色板。WriteableBitmap 变得非常慢,所以我决定缓存 100 个色调色板(以 1% 的增量从 0 到 1)。使用在 WriteableBitmap 的 Community Content 部分找到的 SimpleBitmap 类(http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.writeablebitmap.aspx),生成 Bitmaps 变得容易多了。
对我来说的下一个障碍是重新模板化色调和 Alpha 的滑块,同样,我以前从未做过。我摆弄了几个 ControlTemplate,然后采用了 KAXAML 自己的 Simple Styles 样式并按照我的意愿修改了它。色调滑块背景只是一个带有 LinearGradientBrush 和 7 个 GradientStops 的 Border。
Alpha 滑块和选定的颜色框也有点棘手,我必须承认我并不完全理解显示棋盘格图案的 DrawingBrush 为什么有效。
然而,令我惊讶的是,我认为最棘手的部分实际上是 RGBA/HSLA TextBox! 基本上,问题是这样的。 如果您更新了 R 值,则还必须更新 H、S 和 L。如果更新 H,则必须更新 R,如果更新 S,则必须更新 R。这可能不会那么糟糕,只是从 RGB 到 HSL 的转换代码并不完美。 也就是说,HSL (0.56, .60, .23) 可能不会与 RGB 值完美对齐。 所以,它会四舍五入 RGB 值。 但也许该四舍五入会稍微改变 H 值。 所以我们更改 RGB 值,这会稍微歪斜 H。 最后,我简单地说,如果您更改 H 值,则设置一个标志,更新 RGB 值,当它们试图更新 HSL 值时,检查该标志是否已设置。 如果是,则不更新。 简单来说当然。
使用代码
编辑器的使用方式与其他任何 UserControl 一样。
<Window
x:Class="BrushEditor.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ColorEditor="clr-namespace:Lovatts.ColorEditor;assembly=Lovatts.ColorEditor"
Title="MainWindow"
Height="350"
Width="525">
<ColorEditor:BrushEditor></ColorEditor:BrushEditor>
</Window>
但您也可以绑定到/使用底层的 ViewModels:
ColorEditor colorEditor = new ColorEditor();
colorEditor.ColorEditorViewModel.Color = Colors.Blue;
colorEditor.ColorEditorViewModel.RGB.A = 67;
Lovatts.ColorEditor.BrushEditor brushEditor = new Lovatts.ColorEditor.BrushEditor();
brushEditor.BrushEditorViewModel.BrushType = BrushTypes.Radial;
brushEditor.BrushEditorViewModel.Center = new Point(1, 0);
brushEditor.BrushEditorViewModel.GradientStops.Clear();
brushEditor.BrushEditorViewModel.GradientStops.Add(new GradientStopViewModel(Colors.Blue, 1);
brushEditor.BrushEditorViewModel.GradientStops.Add(new GradientStopViewModel(Colors.Red, 0));
为了方便起见,包含画刷序列化/反序列化方法。
string xml = brushEditor.BrushEditorViewModel.SerializeBrushToXml();
brushEditor.BrushEditorViewModel.DeserializeBrushFromXml(xml);
XML 输出为...
<RadialGradientBrush
Center="1,0" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<RadialGradientBrush.GradientStops>
<GradientStop
Color="#FFFF0000"
Offset="0" />
<GradientStop
Color="#FF0000FF"
Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
关注点
嗯.. 这是我的第一个 CodeProject 提交,大约花了一天时间编写。
更改色调滑块时会出现一个轻微问题,因为它有时会将调色板缩略图捕捉到 RGB 值。
十六进制代码 TextBox 自动设置为 OverType
(使用以下方法),我发现这更用户友好:
private void MakeHexTextBoxOverType()
{
PropertyInfo textEditorProperty = typeof (TextBox).GetProperty(
"TextEditor", BindingFlags.NonPublic | BindingFlags.Instance);
object textEditor = textEditorProperty.GetValue(hexTextBox, null);
// set _OvertypeMode on the TextEditor
PropertyInfo overtypeModeProperty = textEditor.GetType().GetProperty(
"_OvertypeMode", BindingFlags.NonPublic | BindingFlags.Instance);
overtypeModeProperty.SetValue(textEditor, true, null);
}
历史
- 2012年6月19日:发表文章。
- 2012年6月20日:上传源代码
- 2012年6月26日:更新背景