public partial class ColorPicker : UserControl
{
private bool IsPropertyChanging;
private byte FixedAlpha;
private ColorPickerItem CustomItem;
public static readonly DependencyProperty SelectedColorProperty =
DependencyProperty.Register(
"SelectedColor", // プロパティ名を指定
typeof(Color), // プロパティの型を指定
typeof(ColorPicker), // プロパティを所有する型を指定
new FrameworkPropertyMetadata(Colors.White,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
(d, e) => {(d as ColorPicker).OnColorPropertyChanged(e); }));
public Color SelectedColor
{
get { return (Color)GetValue(SelectedColorProperty); }
set { SetValue(SelectedColorProperty, value); }
}
public event SelectionChangedEventHandler SelectionChanged;
public ColorPicker()
{
InitializeComponent();
float r, g, b;
var items = new List<ColorPickerItem>();
for (int i = 0; i < 12; ++i)
{
ColorHelper.HSVtoRGB(0.0f, 0.0f, (float)i / 11.0f, out r, out g, out b);
byte ba = 255;
byte br = (byte)(r * 255.0f);
byte bg = (byte)(g * 255.0f);
byte bb = (byte)(b * 255.0f);
items.Add(new ColorPickerItem()
{
CategoryName = "グレースケール",
Column = i,
Row = 0,
ItemColor = Color.FromArgb(ba, br, bg, bb),
});
}
for (int i = 0; i < 12; ++i)
{
ColorHelper.HSVtoRGB((float)i / 12.0f, 1.0f, 1.0f, out r, out g, out b);
byte ba = 255;
byte br = (byte)(r * 255.0f);
byte bg = (byte)(g * 255.0f);
byte bb = (byte)(b * 255.0f);
items.Add(new ColorPickerItem()
{
CategoryName = "基本の色",
Column = i,
Row = 1,
ItemColor = Color.FromArgb(ba, br, bg, bb),
});
}
for (int j = 1; j < 5; ++j)
{
float s = (float)j / 5.0f;
for (int i = 0; i < 12; ++i)
{
ColorHelper.HSVtoRGB((float)i / 12.0f, s, 1.0f, out r, out g, out b);
byte ba = 255;
byte br = (byte)(r * 255.0f);
byte bg = (byte)(g * 255.0f);
byte bb = (byte)(b * 255.0f);
items.Add(new ColorPickerItem()
{
CategoryName = "その他の色",
Column = i,
Row = 2 + j - 1,
ItemColor = Color.FromArgb(ba, br, bg, bb),
});
}
}
for (int j = 1; j < 4; ++j)
{
float v = 1.0f - (float)j / 5.0f;
for (int i = 0; i < 12; ++i)
{
ColorHelper.HSVtoRGB((float)i / 12.0f, 1.0f, v, out r, out g, out b);
byte ba = 255;
byte br = (byte)(r * 255.0f);
byte bg = (byte)(g * 255.0f);
byte bb = (byte)(b * 255.0f);
items.Add(new ColorPickerItem()
{
CategoryName = "その他の色",
Column = i,
Row = 6 + j - 1,
ItemColor = Color.FromArgb(ba, br, bg, bb),
});
}
}
CustomItem = new ColorPickerItem()
{
CategoryName = "カスタム",
Column = 0,
Row = 9,
ItemColor = Colors.Black,
};
items.Add(CustomItem);
IsPropertyChanging = true;
var src = new ListCollectionView(items);
src.GroupDescriptions.Add(new PropertyGroupDescription("CategoryName"));
Main.ItemsSource = src;
FixedAlpha = SelectedColor.A;
CustomItem.ItemColor = Color.FromArgb(255, SelectedColor.R, SelectedColor.G, SelectedColor.B);
Main.SelectedItem = CustomItem;
IsPropertyChanging = false;
}
private void Hyperlink_Click(object sender, RoutedEventArgs e)
{
var dialog = new System.Windows.Forms.ColorDialog();
dialog.FullOpen = true;
dialog.Color = System.Drawing.Color.FromArgb(SelectedColor.A, SelectedColor.R, SelectedColor.G, SelectedColor.B);
if (System.Windows.Forms.DialogResult.OK == dialog.ShowDialog())
{
SelectedColor = Color.FromArgb(FixedAlpha, dialog.Color.R, dialog.Color.G, dialog.Color.B);
}
}
private void Main_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var item = Main.SelectedItem as ColorPickerItem;
if (null == item) return;
if (!IsPropertyChanging)
{
SelectedColor = Color.FromArgb(FixedAlpha, item.ItemColor.R, item.ItemColor.G, item.ItemColor.B);
if (null != SelectionChanged)
SelectionChanged(this, e);
}
}
public void OnColorPropertyChanged(DependencyPropertyChangedEventArgs e)
{
var item = Main.SelectedItem as ColorPickerItem;
Color col = Colors.Black;
col = (Color)e.NewValue;
if (null != item)
if (item.ItemColor == col) return;
IsPropertyChanging = true;
FixedAlpha = col.A;
CustomItem.ItemColor = col;
Main.SelectedItem = CustomItem;
IsPropertyChanging = false;
}
}
SelectedColorプロパティ (8~20行目)
依存関係プロパティとして作成。
FrameworkPropertyMetadataOptionsでBindsTwoWayByDefaultフラグを立ててデフォルトでバインディングがTwoWayモードで動作するようにしている。
SelectionChangedEventHandler (22、143~144行目)
SelectedColorで色を取得する以外に、選択が変更された時のイベントを処理出来るようにEventHandlerを実装。
データソースを作成 (31~115行目)
GridのRow,Columnを指定しながら色毎のColorPickerItemを作成している。
色はHSV形式で数値を決めた後、RGBへ変換している。
HSVからRGBへの変換についてはこちらを参照
Hyperlink_Clickメソッド (124~133行目)
「その他の色...」がクリックされた時の動作を実装。
カラーダイアログを表示して、OKボタンが押されたらSelectedColorプロパティへ色をセット。
FullOpenプロパティをtrueにするとカスタムカラー作成用のコントロールが最初から見える状態で起動できる。
Main_SelectionChangedメソッド (134~146行目)
ComboBoxの選択が変更された時の処理。
SelectedColorプロパティの値のセットしている。
※SelectedColorプロパティを変えるとOnColorPropertyChangedメソッドが呼び出されるが、そこでComboBoxのSelectedItemが変えられるとMain_SelectionChangedメソッドが呼ばれる。ぐるぐる回ってしまわないようにIsPropertyChangingというフラグで制御している。
OnColorPropertyChangedメソッド (148~162行目)
依存関係プロパティによってSelectedColorの値が変更された時に呼び出される。(15行目)
指定された色をカスタム用のColorPickerItemへセットしそれをComboBoxのSelectedItemにする。
※SelectedItemを変えるとMain_SelectionChangedメソッドが呼び出されるが、そこでSelectedColorプロパティが変えられるとOnColorPropertyChangedメソッドが呼ばれる。ぐるぐる回ってしまわないようにIsPropertyChangingというフラグで制御している。

コメント
コメントを投稿