自定义颜色编辑器的实现与使用

在进行项目开发时,经常需要对颜色进行选择和编辑。市面上有许多优秀的颜色选择器控件,但为了更好地满足特定需求,决定尝试自己实现一个。本文将介绍是如何创建一个基于MVVM模式的颜色编辑器,并解决在实现过程中遇到的一些技术难题。

这个项目是基于MVVM模式的,包含了两个用户控件:ColorEditor和BrushEditor。为了方便使用,它们被打包在一个单独的类库项目中。

颜色选择器的生成

在生成颜色选择器时,遇到了第一个难题。使用WriteableBitmap生成颜色样本非常慢,因此决定缓存100种色调样本(从0到1,以1%的增量)。通过在WriteableBitmap的社区内容部分找到的SimpleBitmap类,生成位图的过程变得更加简单。

滑块的重新模板化

接下来,需要重新模板化Hue和Alpha的滑块,这是之前没有做过的。在尝试了几个ControlTemplates之后,采用了KAXAML的Simple Styles风格,并对其进行了调整。Hue滑块的背景仅仅是一个带有LinearGradientBrush和7个GradientStops的Border。

Alpha滑块和选定颜色框的实现

Alpha滑块和选定颜色框的实现稍微有些棘手,必须承认并不完全理解为什么显示棋盘格图案的DrawingBrush能够工作。

RGBA/HSLA文本框的实现

令惊讶的是,实现RGBA/HSLA文本框实际上是最棘手的部分。问题在于,如果更新了R值,还需要更新H、S和L。如果更新了H,就需要更新R,如果更新了S,也需要更新R。这本身可能不是问题,但RGB到HSL的转换代码并不完美。例如,HSL(0.56, .60, .23)可能不会完全对应一个RGB值。因此,它会四舍五入RGB值。但也许这种四舍五入会稍微改变H值。所以改变了RGB值,这又稍微扭曲了H值。最后,简单地说,如果改变了H值,设置一个标志,更新RGB值,当它们尝试更新HSL值时,检查那个标志是否设置。如果设置了,就不要更新。事后看来很简单。

使用代码

这些编辑器的使用就像使用任何其他UserControl一样。

XAML代码示例:

<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 /> </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));

为了方便起见,包含了Brush的序列化/反序列化方法。

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值。

十六进制代码文本框被自动设置为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日:发布文章。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485