C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: カスタムコントロールでコレクション内アイテム追加時の再描画


(過去ログ 25 を表示中)

[トピック内 13 記事 (1 - 13 表示)]  << 0 >>

■11505 / inTopicNo.1)  カスタムコントロールでコレクション内アイテム追加時の再描画
  
□投稿者/ trickorTreat (1回)-(2007/12/16(Sun) 20:35:16)

分類:[.NET 全般] 

現在、カスタムコントロールを作成しています。

このカスタムコントロールには、コレクション型のプロパティがあるのですが、
デザイナ上でコレクションエディタが起動して、
コレクション内に必要なアイテムが格納されるところまではうまくいきました。

ただ、このコレクション内のアイテムが画面描画に関係しているため、
コレクションエディタでOKボタンを押して確定した際には、
デザイナ上でもこのコントロールについて再描画をかけなくてはいけないのですが、
その方法が分かりません。
一度他のコントロールをクリックしたり、サイズ変更するなどすれば、
再描画されるのですが...。

コレクションエディタは.NET標準のものを利用しています。

どのようにすれば、コレクション追加確定時に
デザイナ上で再描画をかけられるのでしょうか?
ご存知の方どうぞご教示ください。
引用返信 編集キー/
■11516 / inTopicNo.2)  Re[1]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ かずき (13回)-(2007/12/17(Mon) 00:28:48)
かずき さんの Web サイト
ぱっと思いつくのは、外部への変更通知の機能を持つ自前のコレクションを作ることくらいかなぁ…

引用返信 編集キー/
■11520 / inTopicNo.3)  Re[2]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ あんたっちゃぶる (1回)-(2007/12/17(Mon) 09:51:00)
2007/12/17(Mon) 11:19:17 編集(投稿者)

かずきさん

ありがとうございます。
ご教示いただいた方法でためしたいと思います。
デザイナ上でうまく動作するのかは不明ですが。。。

何らかの属性付加をするものとばかり考えており、
教えていただいた方法については考えもしませんでした。
引用返信 編集キー/
■11529 / inTopicNo.4)  Re[1]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ れい (309回)-(2007/12/17(Mon) 12:51:08)
No11505 (trickorTreat さん) に返信
> どのようにすれば、コレクション追加確定時に
> デザイナ上で再描画をかけられるのでしょうか?

コレクションが変更されたときに
カスタムコントロールでInvalidateしてやればできます。
引用返信 編集キー/
■11549 / inTopicNo.5)  Re[2]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ あんたっちゃぶる (2回)-(2007/12/17(Mon) 19:28:54)
No11529 (れい さん) に返信
> コレクションが変更されたときに
> カスタムコントロールでInvalidateしてやればできます。
アドバイスありがとうございます。

れいさんのおっしゃられている、「コレクションが変更されたとき」というのを、
どこでどのようにして受け取るのか(判断するのか)がわからなくて困っています。
通常のプロパティであれば、プロパティset内で
if( base.DesignMode )
{
base.Invalidate();
}
とか書けばいいのでしょうけど、
コレクションの場合、単にコレクションプロパティのsetに書いても
NGのようでして...。

どうやって、デザイナ上でコレクションの要素数もしくは要素そのものが変更されたことを認識するのか、
この点が解決できれば、この問題もクリアできると思うのですが。
引用返信 編集キー/
■11556 / inTopicNo.6)  Re[3]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ ID非公開 (8回)-(2007/12/17(Mon) 22:43:20)
2007/12/17(Mon) 22:58:53 編集(投稿者)
2007/12/17(Mon) 22:50:08 編集(投稿者)

8回目の投稿です。

 はじめまして、ID非公開と申します。
  横槍失礼いたします。
  
  私にわかる範囲でお答えいたします。

  手元の文献によると、
    1.プロパティのSetアクセサ内にMe.Invalidate()を記述し、
    2.OnPaint()内に描画処理を書けばOK
  とのことです。

  ためしに書いてみたコードです。VB2005で動作確認いたしました。
  何かの参考になれば幸いです。

  [追記]既にInvalidateを試されているとのことなので、
      もしかすると的外れな回答かもしれませんが、ご了承下さい。

Imports System.ComponentModel

Public Class InvalidateTest01
Inherits Control

Private m_rect() As Integer = {0, 0, 50, 50}
<Description("円のBoundsを指定"), Category("動作テスト")> _
Public Property EclipseBounds() As Integer()
Get
Return m_rect
End Get
Set(ByVal value As Integer())
If value.Length <> 4 Then
MessageBox.Show("要素数は4つにしてください", "エラー")
Return
End If
m_rect = value
Me.Invalidate()
End Set
End Property
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
Dim r As New Rectangle(m_rect(0), m_rect(1), m_rect(2), m_rect(3))
e.Graphics.FillEllipse(Brushes.Brown, r)
MyBase.OnPaint(e)
End Sub

End Class

   参考文献

     日経BPソフトプレス発行「プログラミングVisualBasic.NET Vol.2活用編」、pp. 195


   以上、横槍失礼いたしました。

 以上です。

引用返信 編集キー/
■11559 / inTopicNo.7)  Re[4]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ ID非公開 (9回)-(2007/12/17(Mon) 23:20:37)
9回目の投稿です。

  やっぱり的外れでした。

  List(Of Integer)にすると、動作しません(!)

  お詫びして訂正いたします。
  あせって投稿してすみませんでした。

以上です。

引用返信 編集キー/
■11560 / inTopicNo.8)  Re[3]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ 渋木宏明(ひどり) (599回)-(2007/12/17(Mon) 23:24:55)
渋木宏明(ひどり) さんの Web サイト
> どうやって、デザイナ上でコレクションの要素数もしくは要素そのものが変更されたことを認識するのか、
> この点が解決できれば、この問題もクリアできると思うのですが。

すでに回答がついてるじゃないですか。

>ぱっと思いつくのは、外部への変更通知の機能を持つ自前のコレクションを作ることくらいかなぁ…

そういった用途にも使えるように System.Collection.ObjectModel.Collection<T> が用意されています。

System.Collection.ObjectModel.Collection<T> を派生して HogeItemCollection を作成し、

・ClearItems
・InsertItem
・RemoveItem
・SetItem

の4メソッドをオーバーライドして、項目の追加/削除が発生した際に ItemAdded, ItemRemoved イベントを上げるようにすればよろしんじゃないかと。

引用返信 編集キー/
■11562 / inTopicNo.9)  Re[4]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ れい (311回)-(2007/12/17(Mon) 23:47:14)
2007/12/17(Mon) 23:56:11 編集(投稿者)

No11560 (渋木宏明(ひどり) さん) に返信
> そういった用途にも使えるように System.Collection.ObjectModel.Collection<T> が用意されています。

これが一番楽ですし、そういった用途のためにあるのでお勧めです。

ですが、べつにそれでなくてもOKです。
カスタムコントロールのプロパティとして
ICollection(+AddRange?)を実装したクラスMyCollectionを割り当てて、
MyCollectionのAddとかInsertとかRemoveとかItem.Setとかで
親コントロールにInvalidateすればいいのですよ。

もちろんこの場合はMyCollectionはカスタムコントロールへの参照を持たないといけないので
普通はコンストラクタでカスタムコントロールを与えますね。
イベントを挙げて通知する手ももちろんOKです。


引用返信 編集キー/
■11563 / inTopicNo.10)  Re[4]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ 渋木宏明(ひどり) (601回)-(2007/12/18(Tue) 00:12:20)
渋木宏明(ひどり) さんの Web サイト
> System.Collection.ObjectModel.Collection<T> を派生して HogeItemCollection を作成し、
>
> ・ClearItems
> ・InsertItem
> ・RemoveItem
> ・SetItem
>
> の4メソッドをオーバーライドして、項目の追加/削除が発生した際に ItemAdded, ItemRemoved イベントを上げるようにすればよろしんじゃないかと。

毎回オリジナルのコレクションを作るのはバカくさいので、ItemAdded, ItemRemoved イベントを上げるように拡張した Collection<T> を作って使いまわしています>自分
引用返信 編集キー/
■11567 / inTopicNo.11)  Re[1]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ ID非公開 (10回)-(2007/12/18(Tue) 03:04:36)
10回目の投稿です。

 大変勉強になりました。
  自作コレクションを作成すると、
  画面の即時再描画に成功しましたが、
  デザイナが変なコードを生成してしまい、
  私の力量では本日は断念せざるを得ませんでした。
  あんたっちゃぶるさんのPCで同じ現象が出ないことをお祈りします。

   私が試した方法
    ・Collection(Of T)を継承
    ・List(Of T)を継承してICollection、IListを再実装
   デザイナが生成したコード
    New TemporaryProject2.myList(Of Integer).Add(10)
    New TemporaryProject2.myList(Of Integer).Add(20)
    New TemporaryProject2.myList(Of Integer).Add(50)
    New TemporaryProject2.myList(Of Integer).Add(50)
    ※myListは自作コレクション

  とりあえず、私はこれで引っ込みます。
  ご迷惑をおかけしました。
  
  P.S.「そんなことより早く寝ろ」といわれるのは承知の上での投稿でした。おやすみなさい。

以上です。

引用返信 編集キー/
■11577 / inTopicNo.12)  Re[2]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ あんたっちゃぶる (4回)-(2007/12/18(Tue) 09:50:07)
みなさまありがとうございます。

イベント通知型による描画という方法で
試してはいるのですが、
どうも[デザイナ上]では正常に再描画される場合とされない場合があり、
まだこの方法なら確実に処理できた、というご報告ができません。

もう少し調べて、またご報告します。

引用返信 編集キー/
■11579 / inTopicNo.13)  Re[2]: カスタムコントロールでコレクション内アイテム追加時の再描画
□投稿者/ れい (312回)-(2007/12/18(Tue) 10:09:37)
No11567 (ID非公開 さん) に返信
>   デザイナが変なコードを生成してしまい、

属性とかきちんとしてないと変になりますね。

時と場合によりますが、
コレクションが専用ならこんな感じで作ります。

Imports System.ComponentModel

Public Class DesignerTest
    Inherits Panel
    Private _item As New MyCollection(Me)

    <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    Public ReadOnly Property Items() As MyCollection
        Get
            Return _item
        End Get
    End Property

    Friend Sub OnCollectionChanged()
        Me.Invalidate()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        For i As Integer = 0 To _item.Count - 1
            e.Graphics.DrawString(_item(i).ToString, Me.Font, Brushes.Black, 0, i * 10)
        Next
        MyBase.OnPaint(e)
    End Sub

    Public Class MyCollection
        Inherits System.Collections.ObjectModel.Collection(Of Integer)
        Private _parent As DesignerTest

        Friend Sub New(ByVal parent As DesignerTest)
            _parent = parent
        End Sub

        Protected Overrides Sub ClearItems()
            MyBase.ClearItems()
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub InsertItem(ByVal index As Integer, ByVal item As Integer)
            MyBase.InsertItem(index, item)
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub RemoveItem(ByVal index As Integer)
            MyBase.RemoveItem(index)
            _parent.OnCollectionChanged()
        End Sub

        Protected Overrides Sub SetItem(ByVal index As Integer, ByVal item As Integer)
            MyBase.SetItem(index, item)
            _parent.OnCollectionChanged()
        End Sub

    End Class

End Class

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -