65.9K
CodeProject 正在变化。 阅读更多。
Home

WPF ColorPicker 和 BrushEditor

starIconstarIconstarIconstarIconstarIcon

5.00/5 (10投票s)

2012年6月19日

CPOL

2分钟阅读

viewsIcon

32910

downloadIcon

1367

类似于 KAXAML 的。

介绍 

嗯,我仍然没有找到一个完美的 WPF ColorPicker 控件来在我的项目中使用。有一些不错的控件,但我最喜欢的是 KAXAML 的,所以,我想我可能会尝试复制它。

背景  

该项目大致上是 MVVM,包含两个用户控件,ColorEditorBrushEditor,并且为了您的方便,它们被打包在一个单独的类库项目中。

我遇到的第一个障碍是尝试生成 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日:更新背景
© . All rights reserved.