いつもお世話になっております、毎度C#で申し訳ありません。
今回、ツリービューを使った設定画面を作ろうとしています。
構想としては、左ペインにツリービュー、右ペインには選択ノードの詳細画面を表示させようと思います。
そのためには、ツリービューのノードと項目を保存するクラスを紐付けなければならないのですが
一体どうやったらいいのかまったく分かりません。
以前リストボックスで作ったときは、リストボックスのインデックス番号があるので簡単でしたが
ツリービューにはインデックスという概念はないようです。階層構造なので。
どうしたらいいのでしょう?解決策を教えてください。
言語:C#
開発環境: Windows XP , Visual Studio 2008
[C#] ツリービューを使った設定画面
Re: [C#] ツリービューを使った設定画面
イメージで言うと、こういうことがやりたいです
- 添付ファイル
-
- Filezilla より
- image.jpg (42.15 KiB) 閲覧数: 8188 回
C,C++,C#,これらを極めることを「3C政策」と言う
Re: [C#] ツリービューを使った設定画面
WinFormsであれば,個人的にはTreeNodeを継承したクラスを作り,そこに右側表示用のコントロールを紐付けられるようにしておきます。
そして,選択されたタイミングで右側に表示されるコントロールをTreeNodeから取得して切り替えます。
まぁ,WPFでDataTemplate使う,でやっちゃえそうな気もしますが。
そして,選択されたタイミングで右側に表示されるコントロールをTreeNodeから取得して切り替えます。
まぁ,WPFでDataTemplate使う,でやっちゃえそうな気もしますが。
Re: [C#] ツリービューを使った設定画面
YuO さんが書きました:WinFormsであれば,個人的にはTreeNodeを継承したクラスを作り,そこに右側表示用のコントロールを紐付けられるようにしておきます。
そして,選択されたタイミングで右側に表示されるコントロールをTreeNodeから取得して切り替えます。
まぁ,WPFでDataTemplate使う,でやっちゃえそうな気もしますが。
おぉ、なるほど!出来そうな気がしてきました!
WPFでの開発予定はありません、とりあえずWinFormでがんばっています。
ところで、「紐付ける」というのは、TreeNodeを継承したクラス内にメンバとして保存用クラスを保持する、ということで
いいのでしょうか?それとも、もっと高度な技があるのでしょうか?
C,C++,C#,これらを極めることを「3C政策」と言う
Re: [C#] ツリービューを使った設定画面
まず,右側に表示する内容はすべてUserControlにします。
次に,TreeNodeを継承したクラスは,UserControlを型とするpublicプロパティを用意しておきます。
setに関してはコンストラクタ引数にして,プロパティはgetのみとしてもよいでしょう。
で,TreeにTreeNodeを継承したクラスのインスタンスを追加する時 (property-set) or 作成する時 (constructor) に,
上記で作成したプロパティに表示するためのUserControlを設定します。
TreeNodeはViewの物なので,UserControlを直接持っても問題ないと思います。
次に,TreeNodeを継承したクラスは,UserControlを型とするpublicプロパティを用意しておきます。
setに関してはコンストラクタ引数にして,プロパティはgetのみとしてもよいでしょう。
で,TreeにTreeNodeを継承したクラスのインスタンスを追加する時 (property-set) or 作成する時 (constructor) に,
上記で作成したプロパティに表示するためのUserControlを設定します。
TreeNodeはViewの物なので,UserControlを直接持っても問題ないと思います。
Re: [C#] ツリービューを使った設定画面
なんとなくイメージは出来るのですが、コード化できません・・・質問させてください。YuO さんが書きました:まず,右側に表示する内容はすべてUserControlにします。
次に,TreeNodeを継承したクラスは,UserControlを型とするpublicプロパティを用意しておきます。
setに関してはコンストラクタ引数にして,プロパティはgetのみとしてもよいでしょう。
で,TreeにTreeNodeを継承したクラスのインスタンスを追加する時 (property-set) or 作成する時 (constructor) に,
上記で作成したプロパティに表示するためのUserControlを設定します。
TreeNodeはViewの物なので,UserControlを直接持っても問題ないと思います。
「上記で作成したプロパティに表示するためのUserControlを設定します」が分かりません。
すいませんできない子で・・・ 教えてください。
C,C++,C#,これらを極めることを「3C政策」と言う
Re: [C#] ツリービューを使った設定画面
ListBoxでも同じだと思うんですけどね……。
単純に,View部品に関係するView部品を持たせてしまうだけですから。
AとBの間に関連がある,というのであれば,それをオブジェクトの中に関連として保持します。
外側に関連を保持するのは,その関連が分散してしまう可能性があります。
ListBoxであってもインデックスを使う,というのは上記に反するので悪手で,
ListBoxに「表示文字列」と「表示用ユーザーコントロール」を取得するためのプロパティを持つクラスのインスタンスを追加しておき,
表示はDisplayMemberで制御,コントロールの変化はSelectedItem経由で行う,というのが正攻法です。
これと同じく,TreeViewでもTreeNodeを継承したクラスには「表示用ユーザーコントロール」を取得するためのプロパティを用意します。
TreeNodeが選択されたら,そのノードから「表示用ユーザーコントロール」を取得し,それを表示します。
ここで,「表示用ユーザーコントロール」をどうやって設定するか,というのにコンストラクタを使うかプロパティへの設定で行うかは,要件次第となります。
WPFのようにModelの型から表示するユーザーコントロールを決定する方法もありますが,WinFormsでは
単純に,View部品に関係するView部品を持たせてしまうだけですから。
AとBの間に関連がある,というのであれば,それをオブジェクトの中に関連として保持します。
外側に関連を保持するのは,その関連が分散してしまう可能性があります。
ListBoxであってもインデックスを使う,というのは上記に反するので悪手で,
ListBoxに「表示文字列」と「表示用ユーザーコントロール」を取得するためのプロパティを持つクラスのインスタンスを追加しておき,
表示はDisplayMemberで制御,コントロールの変化はSelectedItem経由で行う,というのが正攻法です。
これと同じく,TreeViewでもTreeNodeを継承したクラスには「表示用ユーザーコントロール」を取得するためのプロパティを用意します。
TreeNodeが選択されたら,そのノードから「表示用ユーザーコントロール」を取得し,それを表示します。
ここで,「表示用ユーザーコントロール」をどうやって設定するか,というのにコンストラクタを使うかプロパティへの設定で行うかは,要件次第となります。
オフトピック
2006年頃(=VS2005が出た頃)に,プラグインシステムでの設定用に考えた物が土台です。
このため,このような仕組みになっているところはあります。
このため,このような仕組みになっているところはあります。
WPFのようにModelの型から表示するユーザーコントロールを決定する方法もありますが,WinFormsでは
- TreeView / ListViewはデータバインディングに対応していない (選択しているView部品にバインドしているModelが取得できない)
- Modelの型に合わせてコントロールを切り替えるシステムが組み込まれていない
- 添付ファイル
-
- WindowsFormsApplication1.zip
- Visual C# 2010 Express Solution for .NET Framework 2.0
- (17.61 KiB) ダウンロード数: 248 回
Re: [C#] ツリービューを使った設定画面
YuO さんが書きました:ListBoxでも同じだと思うんですけどね……。
単純に,View部品に関係するView部品を持たせてしまうだけですから。
AとBの間に関連がある,というのであれば,それをオブジェクトの中に関連として保持します。
外側に関連を保持するのは,その関連が分散してしまう可能性があります。
ListBoxであってもインデックスを使う,というのは上記に反するので悪手で,
ListBoxに「表示文字列」と「表示用ユーザーコントロール」を取得するためのプロパティを持つクラスのインスタンスを追加しておき,
表示はDisplayMemberで制御,コントロールの変化はSelectedItem経由で行う,というのが正攻法です。
これと同じく,TreeViewでもTreeNodeを継承したクラスには「表示用ユーザーコントロール」を取得するためのプロパティを用意します。
TreeNodeが選択されたら,そのノードから「表示用ユーザーコントロール」を取得し,それを表示します。
ここで,「表示用ユーザーコントロール」をどうやって設定するか,というのにコンストラクタを使うかプロパティへの設定で行うかは,要件次第となります。オフトピック2006年頃(=VS2005が出た頃)に,プラグインシステムでの設定用に考えた物が土台です。
このため,このような仕組みになっているところはあります。
WPFのようにModelの型から表示するユーザーコントロールを決定する方法もありますが,WinFormsではという理由から不向きだと思います。
- TreeView / ListViewはデータバインディングに対応していない (選択しているView部品にバインドしているModelが取得できない)
- Modelの型に合わせてコントロールを切り替えるシステムが組み込まれていない
ありがとうございます!本当に参考になります!
いただいたコードを元に、自分なりに作ってみました!(例外処理とかは究極に手を抜いています)
ただ、ひとつ問題が・・・
このプロジェクトでは、入力された情報を、別途ファイルに保存し、次回起動時に復元しなければならないのですが・・・
ツリービューと情報クラスとの紐をどうやって保存するか見当もつきません・・・
どうしたらいいのでしょうか、引き続きお願いできましたら幸いです。
- 添付ファイル
-
- test.zip
- Visual Studio 2008 Express Edition
- (10.64 KiB) ダウンロード数: 173 回
C,C++,C#,これらを極めることを「3C政策」と言う
Re: [C#] ツリービューを使った設定画面
ツリービューと情報クラスは紐付く必要はないでしょう。オカピーα さんが書きました:このプロジェクトでは、入力された情報を、別途ファイルに保存し、次回起動時に復元しなければならないのですが・・・
ツリービューと情報クラスとの紐をどうやって保存するか見当もつきません・・・
どうしたらいいのでしょうか、引き続きお願いできましたら幸いです。
Form自体がModelへの参照は保持していると思うので,Model自身かその一部をユーザーコントロールに渡します。
このあたりは,TreeNodeへの拡張と同じ方法です。
ただし,UserControlをデザイナで使うためにはデフォルトコンストラクタが必要なので,
private Models.Model _model;
public UserControl1 () // デザイナで必要
{
InitializeComponents();
_model = null; // とりあえず,モデルをnullにしておく
}
public UserControl1 (Models.Model model) : this() // デフォルトコンストラクタを必ず呼び出す
{
_model = model; // 渡されたモデルを保持
}
protected override void OnLoad (EventArgs e)
{
base.OnLoad(e);
if (_model != null) modelBindingSource.DataSource = _model; // データバインドする
}
Re: [C#] ツリービューを使った設定画面
YuO さんが書きました:ツリービューと情報クラスは紐付く必要はないでしょう。オカピーα さんが書きました:このプロジェクトでは、入力された情報を、別途ファイルに保存し、次回起動時に復元しなければならないのですが・・・
ツリービューと情報クラスとの紐をどうやって保存するか見当もつきません・・・
どうしたらいいのでしょうか、引き続きお願いできましたら幸いです。
Form自体がModelへの参照は保持していると思うので,Model自身かその一部をユーザーコントロールに渡します。
このあたりは,TreeNodeへの拡張と同じ方法です。
ただし,UserControlをデザイナで使うためにはデフォルトコンストラクタが必要なので,のような書き方になります。private Models.Model _model; public UserControl1 () // デザイナで必要 { InitializeComponents(); _model = null; // とりあえず,モデルをnullにしておく } public UserControl1 (Models.Model model) : this() // デフォルトコンストラクタを必ず呼び出す { _model = model; // 渡されたモデルを保持 } protected override void OnLoad (EventArgs e) { base.OnLoad(e); if (_model != null) modelBindingSource.DataSource = _model; // データバインドする }
モモモモモモモモモデルって何でしょうか
まさかデザインパターンでしょうか?デザインパターンが出るんでしょうか?
デザインパターンがお出ましするんでしょうか!?うわぁー!世直しだぁあー!!助けてくれー!!
・・・すいません取り乱しました もうちょっと簡単な方法はないですか 泣きそうです(´;ω;`)
C,C++,C#,これらを極めることを「3C政策」と言う
Re: [C#] ツリービューを使った設定画面
モデルというのは,単純にView,見た目以外の部分を指しています。
情報クラスはモデルの一部のはずです。
結局の所,
これらをデータバインドなり,手作業でバインドするなりして,コントロールの状態と情報を持ったクラスの状態を一致させるようにします。
この時,情報を持ったクラスにはView情報を極力含ませないようにします。
保存や復元は,この情報を持ったクラスの保存や復元であり,BinaryFormatterやXmlSerializerといったSerializerを使うことで簡単に保存・復元ができます。
GUIアプリケーションを単純に作るだけであれば力業でもある程度できますが,大規模になればなるほど,Presentation Domain Separation (PDS)を考慮したアーキテクチャの採用が必要になります。
有名どころとしてMVCがあり,その派生として色々あるわけですが……。
情報クラスはモデルの一部のはずです。
結局の所,
- フォームで必要な情報は,クラスにまとめておく
- ユーザーコントロールで必要な情報は,クラスにまとめておく
- フォームまたはユーザーコントロールに属するコントロール (ユーザーコントロール含む) で必要な情報は,そのフォームまたはユーザーコントロールで必要な情報が集まったクラスのプロパティとして提供する
これらをデータバインドなり,手作業でバインドするなりして,コントロールの状態と情報を持ったクラスの状態を一致させるようにします。
この時,情報を持ったクラスにはView情報を極力含ませないようにします。
保存や復元は,この情報を持ったクラスの保存や復元であり,BinaryFormatterやXmlSerializerといったSerializerを使うことで簡単に保存・復元ができます。
オフトピック
効率その他の理由で,現在ではDataContractSerializer等が推奨されますが,.NET 3.0以降なので除外。
ref) neue cc - .NET(C#)におけるシリアライザのパフォーマンス比較
あと,上記の方法で作ったクラスはView由来のクラスなので,PDS的にはP側のクラス。本来ならD側のクラスがあって,そちらをシリアライズしたいところ。
ref) neue cc - .NET(C#)におけるシリアライザのパフォーマンス比較
あと,上記の方法で作ったクラスはView由来のクラスなので,PDS的にはP側のクラス。本来ならD側のクラスがあって,そちらをシリアライズしたいところ。
GUIアプリケーションを単純に作るだけであれば力業でもある程度できますが,大規模になればなるほど,Presentation Domain Separation (PDS)を考慮したアーキテクチャの採用が必要になります。
有名どころとしてMVCがあり,その派生として色々あるわけですが……。
- MOVEは望まれなかった子 - the sea of fertility
[翻訳]MVCは死んだ。MOVEするときがきた - きしだのはてなへの反論文書にして,PDSやMVC系アーキテクチャについての責務の詳細な説明 - MVVMパターンとイベント駆動開発、そしてMVC/MVP/PMパターンとの関係 – 何故MVVMなのか - the sea of fertility
前記の尾上氏の別の記事。スライドにMVCの説明あり。あと,尾上氏のサイトには,8/4 わんくま同盟 大阪勉強会 #50で2コマ話してきました! - the sea of fertilityのような良記事がたくさんあります。 - MVCモデルについて - GeekなNooblog
JavaベースでのUIアーキテクチャについての考察。PDSは言語に囚われないので,C#以外の文書でも役に立ちます。 - 開発者が知っておくべき、6つのUIアーキテクチャ・パターン - @IT
各種UIアーキテクチャの一覧と考察。
オフトピック
こういう時の参考URLを引っ張ってくるのに,【雑談】mixC++勉強会@Tokyo • C言語交流フォーラム ~ mixC++ ~で使ったスライドの末尾の参考資料を使うのですが,
Presentation-Domain Separationでググったらなんかslideshareに上げたスライドが5番目 (かつ尾上氏の記事の下かつ尾上氏の有用なスライドの上) とかいう,非常に申し訳ない位置に来ていてびっくり。
というか,なぜ尾上氏のわんくま大阪#50のスライドが私の下にあるのか理解に苦しむ……
Presentation-Domain Separationでググったらなんかslideshareに上げたスライドが5番目 (かつ尾上氏の記事の下かつ尾上氏の有用なスライドの上) とかいう,非常に申し訳ない位置に来ていてびっくり。
というか,なぜ尾上氏のわんくま大阪#50のスライドが私の下にあるのか理解に苦しむ……