ユーザーコントロールを作成する(3)

今回は、前回作成したコントロールに公開イベントを追加します。

作成したコントロールにはチェックボックスが付いています。このチェックボックスのチェック状態が変更されたときに発生するCheckedChangedイベントを追加してみましょう。

まずはイベントを宣言します。

public event EventHandler<EventArgs> CheckedChanged;

次に、公開イベントの追加を下記のように行います。

ここで[Browsable(true)]とすることで、プロパティウィンドウの雷マークをクリックしたときのイベント一覧に表示されるようになります。また、[Description()]を使用することで、イベントの説明を表示させることができます。

/// <summary>
/// チェック状態が変更された場合に発生します
/// </summary>
/// <param name="e"></param>
[Browsable(true)]
[Description("チェック状態が変更されるときに発生するイベントです")]
protected virtual void OnCheckedChanged(EventArgs e)
{
    EventHandler<EventArgs> eventHandler = CheckedChanged;

    if (eventHandler != null)
    {
        eventHandler(this, e);
    }
}

最後に、イベントを発生させる方法について押さえておきましょう。
作成したいイベントはいつ発生させたらよいでしょうか?ここでは当然、チェック状態が変わったときですよね。
ということで、Checkedプロパティで行うこととしました。set {~}の中を見ていただきたいのですが、OnCheckedChangedを呼んで、イベントを発生させています。(ここはチェック状態セットされるときに実行される場所ですよね。なので、ここでイベントを発生させているというわけです)

[Browsable(true)]
[Description("テキスト入力エリアの表示/非表示を切り替えます。")]
[Category("動作")]
public bool Checked 
{
    get
    {
        return checkBox1.Checked;
    }
    set
    {
        checkBox1.Checked = value;

                    
        // チェック状態が変更されたのでCheckedChangedイベントを発生させる
        OnCheckedChanged(EventArgs.Empty);
    }
}

ユーザーコントロールは特別難しいモノではありません。アイデア次第では、非常に便利なコントロールを作成することが可能なので、是非チャレンジしてみてください。

ユーザーコントロールを作成する(2)

前回、チェックボックス付きのユーザーコントロールを作成しました。

今回は、このコントロールを少しカスタマイズしていきたいと思います。


リサイズ対応

ユーザーコントロールは、標準で提供されているコントロールと同様にリサイズを行うことができます。

しかし、前回配置したチェックボックスとテキストボックスはリサイズに対する設定を何も行っていません。このため、ユーザーコントロールをリサイズしても、チェックボックスとテキストボックスは、配置したときのサイズのままとなり、ユーザーコントロールの外枠だけが変わります。

ユーザーコントロールのサイズに合わせて、配置したコントロールのサイズを変えるには、Dockプロパティを使用したり、ユーザーコントロールのResizeイベント内で調整を行う必要があります。

今回は、テキストボックスの横幅だけがリサイズするよう調整を行ってみます。

まず、テキストボックスの幅はユーザーコントロールの幅に合わせるために、AnchorプロパティにTop,Left,Rightを設定します。これで、横方向のリサイズに対応することができます。

次に、縦方向のリサイズですが、高さはテキストボックスと常に等しくなるようにします。

そこで、Resizeイベントに下記のようなコードを記述します。

private void CheckTextBox_Resize(object sender, EventArgs e)
{
    // ユーザーコントロールの高さは常にtextBox1に合わせる
    this.Height = textBox1.Height;
}

以上でリサイズ対応は終了です。


プロパティを作成する

今度は、ユーザーコントロールにプロパティを追加して、プロパティウィンドウに表示されるようにしていきます。

まずは、チェックボックスのチェック状態を変更できるようにます。プロパティ名はCheckedとします。

コードは下記のようになります。見てわかるとおり、普通のプロパティの作成方法と何らかわりません。

public bool Checked 
{
    get
    {
        return checkBox1.Checked;
    }
    set
    {
        checkBox1.Checked = value;
    }
}

プロパティを公開する

プロパティは作成しただけでは駄目です。公開設定をしてあげないと、プロパティウィンドウに表示されません。(もちろんプロパティウィンドウに表示する必要がない場合は設定する必要はありません)

プロパティを公開するには Browsable属性にtrueを指定する必要があります。実際のコードは下記のようになります。これでプロパティウィンドウに表示されるようになります。

[Browsable(true)]
public bool Checked 
{
    get
    {
        return checkBox1.Checked;
    }
    set
    {
        checkBox1.Checked = value;
    }
}

プロパティウィンドウに説明を表示する

プロパティを公開することができたので、今度は説明が表示されるようにしてみましょう。

プロパティウィンドウの下側に表示する説明は、Description属性を使用します。実例は下記の通りです。

[Browsable(true)]
[Description("テキスト入力エリアの表示/非表示を切り替えます。")]
public bool Checked 
{
    get
    {
        return checkBox1.Checked;
    }
    set
    {
        checkBox1.Checked = value;
    }
}

プロパティのカテゴリーを設定する

プロパティはカテゴリーを設定することができます。こちらはCategory属性で設定します。

[Browsable(true)]
[Description("テキスト入力エリアの表示/非表示を切り替えます。")]
[Category("動作")]
public bool Checked 
{
    get
    {
        return checkBox1.Checked;
    }
    set
    {
        checkBox1.Checked = value;
    }
}

ここまで入力できたら、ビルドして
フォームにコントロールを貼り付けてみます。

コントロールのリサイズは横方向のみであることを確認してください。
また、プロパティウィンドウには Checkedプロパティが表示されカテゴリーが「動作」となっていること、説明に「テキスト入力エリアの表示/非表示を切り替えます。」と表示されることを確認しましょう。

Checkedプロパティの値が変更されると、チェックボックスのチェック状態が変わることも確認しましょう。

プロパティウィンドウ

 

次回は、イベントを作成する方法について説明します。

ユーザーコントロールを作成する(1)

今回から数回に分けて、Windowsアプリでのユーザーコントロールの作成方法について説明します。

ユーザーコントロールは、新規クラスから作成することもできますし、プロジェクトメニューの[追加]-[ユーザーコントロール]で作成することもできます。

また、作成するユーザーコントロールはdllにすることもできますし、自身が使うWindowsフォームアプリケーション内で直接作成することもできます。

今回は、Windowsフォームアプリケーションに、直接自作のコントロールを作ってみたいと思います。

お題は、「チェックボックス付きのテキストボックス」コントロールです。

チェックボックスがチェック状態のときはテキストが入力でき、チェックが外されたらテキストを入力できないようにするコントロールです。

作成するコントロールの実行イメージは下図の通りです。

作成イメージ


新規プロジェクトを作成したら、プロジェクトメニューから[追加]-[ユーザーコントロール]をクリックして、「CheckTextBox」という名前で保存します。

ユーザーコントロールの追加

CheckTextBoxのデザイナーが開くので、下図のようにCheckBoxとTextBoxを配置します。CheckBoxのTextプロパティには空文字をセットして、チェックマークの部分だけを残しています。

コントロールの配置

次に、CheckTextBox(ユーザーコントロール)の高さを、配置したTextBoxと同じ高さに設定します。

リサイズ後のコントロール

あとは、TextBoxのReadOnlyプロパティをfalseに設定しておきます。

デザインは以上です。

今度は、チェック状態に合わせてTextBoxの有効/無効を切り替える処理を作成します。

次にチェック状態変更時の処理を書きます。

貼り付けてあるCheckBoxのCheckedChangedイベントを作成して、コードを以下のようにします。

private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    // チェック状態の時は入力ができるようにする
    textBox1.ReadOnly = !checkBox1.Checked;
}

ここまで入力ができたら、ビルドをしてみましょう。

ビルドが成功すると、ツールボックスにCheckTextBoxが表示されます。

ツールボックスに表示されたユーザーコントロール

あとは、CheckTextBoxを自分のフォームに貼り付けて、動作を確認してみましょう。

チェック状態の時は入力ができ、未チェック状態のときは入力ができないコントロールとなっていればOKです。

作成したユーザーコントロールのテスト

次回は、公開プロパティの作成方法やコントロールのリサイズ対応などについて紹介する予定です。

[Tips] 拡張メソッドを作成する

Stringクラスに拡張メソッドを追加してみたので、そのメモです。

今回追加したのは、AddDoubleQuoteというメソッドで、実行すると文字列の前後にダブルクォーテーションを付加するというものです。

通常、文字列の前後にダブルクォーテーションを付加するには以下のようなコードを記述します。

string sData = "\"" + "Hello" + "\"";

AddDoubleQuoteメソッドなら、下記のようにするだけで文字列の前後にダブルクォーテーションを付けることができます。

string sTest = "Hello";
sTest.AddDoubleQuote();

それでは、拡張メソッドのコードです。

static class StringExtentions
{
    public static string AddDoubleQuote(this string str)
    {
        return "\"" + str + "\"";
    }
}

と、たったこれだけです。

このクラスをプロジェクトの中に入れておけば、AddDoubleQuoteメソッドを、あたかもstring型のインスタンスメソッドのように呼び出すことができます。

拡張メソッドのキモは、引数にthisキーワードを持つ静的メソッドを定義するということです。

簡単ですので、皆さんも是非試してみてください。

[Windows アプリ] コントロールを文字列で操作する

業務の中で、コントロールのプロパティ値を外部ファイルに持たせて、動的に変更したいという要望がありました。

そこで、Controlsコレクションを使用したので、そのメモです。他にも手法はあるのですが、今回はこれを採用です。


フォーム上に貼り付けたコントロールは、Controlsコレクションを使用して取得することができます。

たとえば、フォーム上のコントロールのすべてのTextプロパティを変更するには、下記のような書き方ができます。

あくまでもTextプロパティを持つコントロールのみが配置されているという想定です。

VBの例

Dim I As Integer = 1

For Each c As Control In Me.Controls
    c.Text = "Text" & I
    I += 1
Next

C#の例

int i = 1;
foreach (Control c in this.Controls)
{
    c.Text = "Text" + i.ToString();
    i++;
}

さて、ここからが本題です。

Controlsコレクションを使用して、コントロールを操作する場合は、インデックスによる方法と、文字列でコントロールを特定する方法があります。

VBの例

'インデックスによる指定
Controls(インデックス).プロパティ = 値
'コントロール名(文字列)による指定
Controls(コントロール名).プロパティ = 値

C#の例

// インデックスによる指定
Controls[インデックス].プロパティ = 値
// 文字列による指定
Controls[コントロール名].プロパティ = 値

Label1というコントロールのTextプロパティに”HIRO”という文字列を設定する場合は、下記のように記述することができます。
VBの例

Me.Controls["Label1"].Text = "HIRO"

C#の例

this.Controls["label1"].Text = "HIRO";