質問者
色を選択できる DataGridViewComboBoxColumn / Cell を作りたい

全般的な情報交換
-
- 方法 : ComboBox コントロールにサイズ変更可能なテキストを作成する
を参考に、色を選択できる DataGridViewComboBoxColumn / Cell を組み込んで
みました。でも、未達です。
何が未達かというと、-
ComboBox で色の選択後に、Cell の BackColor を選択色に変えられない -
あらかじめ色 Item をもつ拡張コントロール ColoredComboBox を流用したい
-
ComboBox.DrawItem イベントハンドラを削除できない
以上のことを解決したいのですが、どうにも分かりません。
どうやったら実現できるのか、お知恵をお貸しください。
+ 追記
1 への対応を追記していますが、それが正しい処理かどうか不明なので、
詳しい方の助言を期待します。
参考画像 (1) 最初の画面
参考画像 (2) GetFormattedValue() 追加後
サンプルコード
Code Snippetusing System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;namespace DrawColoringComboBoxItems
{
public class ColoredComboBoxColumn : DataGridViewComboBoxColumn
{
public ColoredComboBoxColumn()
: base()
{
base.CellTemplate = new ColoredComboBoxCell();
}public override DataGridViewCell CellTemplate
{
get
{
return base.CellTemplate;
}
set
{
if (value != null&& !value.GetType().IsAssignableFrom(typeof(ColoredComboBoxCell)))
{
throw new InvalidCastException("Must be a ColoredComboBoxCell");
}
base.CellTemplate = value;
}
}
}public class ColoredComboBoxCell : DataGridViewComboBoxCell
{
public ColoredComboBoxCell()
: base()
{ }public override void InitializeEditingControl(
int rowIndex,
object initialFormattedValue,
DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
ComboBox comboBox = this.DataGridView.EditingControl as ComboBox;
if (comboBox != null)
{
comboBox.DrawMode = DrawMode.OwnerDrawFixed; ........................... (1)
comboBox.DrawItem -= new DrawItemEventHandler(comboBox_DrawItem);comboBox.DrawItem += new DrawItemEventHandler(comboBox_DrawItem); ...... (2)
}
}private void comboBox_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index >= 0)
{
ComboBox comboBox = (ComboBox)sender;
string colorName = comboBox.Items[e.Index].ToString();
Color color = this.getColor(colorName);
Rectangle rect = e.Bounds;e.Graphics.FillRectangle(new SolidBrush(color), rect);
StringFormat fmt = new StringFormat();
fmt.Alignment = StringAlignment.Near;
fmt.LineAlignment = StringAlignment.Near;
e.Graphics.DrawString(colorName, comboBox.Font, Brushes.White, rect, fmt);
}
}protected override object GetFormattedValue(
object value,
int rowIndex,
ref DataGridViewCellStyle cellStyle,
System.ComponentModel.TypeConverter valueTypeConverter,
System.ComponentModel.TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts context)
{
if (value != null)
{
cellStyle.BackColor = this.getColor(value.ToString());
}
return base.GetFormattedValue(
value, rowIndex, ref cellStyle, valueTypeConverter,formattedValueTypeConverter, context);
}private Color getColor(string colorName)
{
switch (colorName.ToUpper())
{
case "RED" : return Color.Red;
case "ORANGE" : return Color.Orange;
case "YELLOW" : return Color.Yellow;
case "GREEN" : return Color.Green;
case "BLUE" : return Color.Blue;
case "NAVY" : return Color.Navy;
case "PURPLE" : return Color.Purple;
default : return Color.White;
}
}
}
}- (1)
- 元々 DataGridViewComboBoxColumn / Cell では DrawMode は使えないのですが、
cast して強引に呼び出しています。 - (2)
- DrawItem で描画を行うようにイベントハンドラを設定しています。
-
すべての返信
-
custarさん、果敢に挑戦されていますね。
カスタムコントロールをDataGridViewで使う方法については以下のページが参考になると思います。
私も同様のことをしようとしていますが全く別の原因で引っかかっています。
custarさんの場合は素直にComboBoxを拡張なさっているのですんなりいくような気がします。
http://msdn2.microsoft.com/ja-jp/library/system.windows.forms.idatagridvieweditingcontrol(VS.80).aspx
http://dobon.net/vb/dotnet/datagridview/maskedtextboxcolumn.html
追記
あれ?、既にやっておられますね。
どこかで引っかかったのでしょうか。
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2723834&SiteID=7 -
三輪の牛 さん、情報ありがとうございます。
まさしくこちらでも CalendarColumn を参考に組んでいます。いずれも取るべ
き手順は同じでしょう。
但し、今回私がやっているのは、既存の DataGridViewComboBox に、あらかじ
め色 Item を付けて表示させるだけ、という点が違います。-
CaledarColumn の例ならば、土日のセルの背景色を付けて DateTimePicker を表示させたり、
-
MaskedTextbox の例ならば、既存データとバインドしてあらかじめ代入させて表示させたり
するようなことをやろうとしています。
DataGridViewComboBoxEditingControl をどう扱うか、考えていたところです。
既に IDataGridViewEditingControl を実装しているであろう
DataGridViewComboBoxEditingControl を継承しないのはもったいないんじゃないかと。
単に、DataGridViewComboBoxEditingControl を継承したものが、あらかじめ色
Item をもつ EditingControl であればいいだけなんじゃないかと。既に ColoredCombBox は実装済みなので。
追記 (2008-03-18)
Code Snippet- DataGridViewComboBoxEditingControl クラス (System.Windows.Forms)
EditingControlShowing イベントを処理すると、
セルが編集モードになったときに、編集コントロールのカスタムの初期化を実行できます。...ということは、EditingControl への ColoredComoboBox 継承は無し!?
# そうは言われても、出来ると密かに予想しています。ColoredComboBoxColumn.cs を DataGridView から分離できないのかも。
ま、ColoredComboBoxColumn を含んだ拡張 DataGridView にすればいいだけですが。
Code Snippetコントロールの表示特性をカスタマイズするには、
DataGridViewEditingControlShowingEventArgs.Control プロパティ
によって返されるコントロールのプロパティを設定するのではなく、DataGridViewEditingControlShowingEventArgs.CellStyle プロパティ
によって返されるオブジェクトのプロパティを設定します。留意点。
-
-
三輪の牛 さんからの引用
追記
あれ?、既にやっておられますね。
どこかで引っかかったのでしょうか。
http://forums.microsoft.com/MSDN-JA/ShowPost.aspx?PostID=2723834&SiteID=7
(1) 1つの DataGridViewCell で複数のコントロールをホストするには
(2) 標準の DataGridViewCell より大きい UserControl を常時ホストする場合、行の高さや列の幅を調整するには
(1) はトーンダウンしています。下記 (2) をメインにしようとしてます。
何故なら応用が利きそうだから。
しかし、編集時に UserControl をセル上に被せる、という (1)、(2) のや
り方にしっくり感がないので、ホストしようかと考え出しています。 -
-
三輪の牛 さんからの引用
DataGridViewComboBoxEditingControl を継承して利用するのですか。
そのつもりです。
三輪の牛 さんからの引用
DataGridViewComboBoxEditingControl is-a ComboBox なので、
折角作った ColoredComboBox が利用できないと思います。
色付き ComboBox ってどうやって作るんだ?という疑問からの試作ですから、
色付け部分のみ流用します。
三輪の牛 さんからの引用
DataGridViewComboBoxCell や DataGridViewComboBoxColumn の方を継承して利用するのは OK と予想しています。
はい。
三輪の牛 さんからの引用
コンボボックスのための仕組みを利用しないと委譲コードが多くなりそうです
から、うまく利用して減らしたいですね。
大凡 (おおよそ) の実装は済みましたが、値の引き渡しのところ辺りで例外発生中です。
選択後の色名が出なくなってしまいました。ColoredComboBox を組み込む前までは何も出ませんでしたが。
Code Snippetpublic class ColoredComboBoxCell : DataGridViewComboBoxCell
{
public ColoredComboBoxCell()
: base()
{ }public override void InitializeEditingControl(
int rowIndex,
object initialFormattedValue,
DataGridViewCellStyle dataGridViewCellStyle)
{
base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);
ColoredComboBox comboBox = this.DataGridView.EditingControl as ColoredComboBox;
if (comboBox != null)
{
comboBox.SelectedValue = (this.Value != null) ? this.Value.ToString() : null;comboBox.activate(); ..................................................... (3)
}
}public override Type EditType
{
get { return typeof(ColoredComboBox); }
}protected override object GetFormattedValue(
object value,
int rowIndex,
ref DataGridViewCellStyle cellStyle,
System.ComponentModel.TypeConverter valueTypeConverter,
System.ComponentModel.TypeConverter formattedValueTypeConverter,
DataGridViewDataErrorContexts context)
{
if (value != null)
{
cellStyle.BackColor = ColoredComboBox.getColor(value.ToString());
}return base.GetFormattedValue(
value, rowIndex, ref cellStyle, valueTypeConverter,
formattedValueTypeConverter, context);
}}
public class ColoredComboBox : DataGridViewComboBoxEditingControl
{
public ColoredComboBox()
: base()
{ }~ColoredComboBox()
{
this.Items.Clear();
}public void activate()
{
this.Items.AddRange(new object[] {"", "Red", "Orange", "Yellow", "Green", "Blue", "Navy", "Purple" });
this.DrawMode = DrawMode.OwnerDrawFixed;
}protected override void OnDrawItem(DrawItemEventArgs e)
{
base.OnDrawItem(e);if (e.Index >= 0)
{
string colorName = this.Items[e.Index].ToString();
Color color = ColoredComboBox.getColor(colorName);
Rectangle rect = e.Bounds;e.Graphics.FillRectangle(new SolidBrush(color), rect);
StringFormat fmt = new StringFormat();
fmt.Alignment = StringAlignment.Near;
fmt.LineAlignment = StringAlignment.Near;
e.Graphics.DrawString(colorName, this.Font, Brushes.White, rect, fmt);
}
}public static Color getColor(string colorName)
{
switch (colorName.ToUpper())
{
case "RED" : return Color.Red;
case "ORANGE" : return Color.Orange;
case "YELLOW" : return Color.Yellow;
case "GREEN" : return Color.Green;
case "BLUE" : return Color.Blue;
case "NAVY" : return Color.Navy;
case "PURPLE" : return Color.Purple;
default : return Color.White;
}
}
}
元々 DataGridView.EditingControl は DataGridViewComboBoxEditingControl
なので、色付き Item なんてもっていません。(3) で色付き Item を追加する
処理を呼び出しています。
なんか他にやり方がありそうなんですけど。+ 追記
色 Items を一々追加するのが面倒なので、それをもつクラスを作ろうとしたけど、
失敗中。そこまでしなければ出来ているので、後日、時間の空いた時に取り掛かる。
一旦閉じます。
三輪の牛 さん、アドバイスありがとうございます。
-