HSVとRGBの両方で色を編集できるようにしてみた。
入手先
TrackBarと少数値の問題
TrackBarは整数値しか扱えない。 目盛りの最小値は1。少数値にできない。 0.0~1.0を任意の少数桁で扱うことができない。 0~100に変換する必要がある。
Bindingの問題
ハードコード
プロパティを特定するために文字列をハードコーディングすることになってしまう。 HSVのうち、Hプロパティを特定するために、"H"という文字列をハードコーディングすることになる。
public partial class ColorEditorForm : Form
{
public ColorEditorForm()
{
numericUpDown1.DataBindings.Add(
(new System.Windows.Forms.Binding(
"Value",
bindingSourceHsv,
"H",
true,
System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
}
}
public class Hsv : INotifyPropertyChanged
{
private float _h;
public float H { get { return _h; } set { _h = value; NotifyPropertyChanged("H"); } }
}
何が問題か
修正し忘れ
もしプロパティ名が変更になった場合、ハードコーディングした文字列の部分を修正し忘れる可能性がある。 プロパティ名の場合はコンパイルエラーになる。 しかし、文字列はエラーにならない。
動作するなら問題ないかもしれないが、誤解や迷いを生む可能性もあるしわかりにくい。
デタラメな名前でも可
プロパティ名とdataMember文字列は直接の関係は何もない。 デタラメな名前でも付けることができてしまう。
動作するなら問題ないかもしれないが、誤解や迷いを生む可能性もあるしわかりにくい。
IDEで自動修正できない
修正したら「DataBindings.Add」と「INotifyPropertyChanged継承クラス」の両方を修正する必要がある。 IDEの「名前の変更」で自動反映してくれない。
連動
BindingSourceでの連動はかえって面倒になってしまう。
R,G,Bのうち、各要素のNumericとTrackBarを連動させることだけなら簡単。 しかし、H,S,VのNumericとTrackBarも連動させることはかえって面倒になる。
PropertyChangedEventHandlerのイベントを発火させるタイミングを制御する必要がある。 普通に実装するとH,S,Vの値を一つずつ設定するたびにイベントを発火してしまう。 そのせいで、UIで入力した値がH,S,V各変数に代入される前に、前の値の状態で発火してしまう。
BindingConveter
HSVとRGBの各UI連動はBindingConveterで解決できると思われる。
そもそも、HSVとRGBは表現が異なるだけで同じ値。 なのに、Bindingできない。
調べてみると、WPFではBindingConveterというのがあるらしい。 Windows Form Applicationで使えるという情報はなかった。
イベント駆動とモデル駆動
Formはイベント駆動ベース。WPFはモデル駆動。 Bindingはモデル駆動の仕組み。
Formはイベント駆動なのにDataBindingというモデル駆動の仕組みを取り入れたせいでチグハグになっている。
- コントロールのValueプロパティとモデル用クラスのプロパティが重複する
- BindingConveterが使えない
コードの冗長さ
連動のせいでコードが冗長になってしまった。 配列を使えば短くはできる。もっとスマートは方法はないものか。 イベント駆動でなくモデル駆動なら…。