質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

1634閲覧

TreeViewとListBoxを使って表示連携するときのベストな実装

siksmtt

総合スコア20

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

1クリップ

投稿2019/05/15 08:21

前提・実現したいこと

WPF(MVVMパターン)を使ってツリー(TreeView)とリスト(ListBox)の表示連携をしたいと思っています。
例えば以下のような構成だとします。

<TreeView イメージ> 日本 |  ーー東日本     |     ーー東北     --関東  ーー西日本
<関東を選択時のListBox> 東京 神奈川 埼玉 <東日本を選択時のListBox> 青森 秋田 東京 神奈川

上記のように、ListBoxに47都道府県のリストを入れ、
各地域を選択したときにListBoxに表示される一覧を更新させるアプリケーションを作っています。

ロジックについて

現時点では47都道府県(47アイテム)を持つリストをバインディングし、
ツリービューの選択遷移のイベントにてListBoxItemのVisibilityCollapsedなどをsetしている動きになっています。

前提:47アイテムを持つ "一覧"という名称のリストがある。各アイテムは"件名"・"ノードパス"・"表示"プロパティを持つ。 "表示"プロパティはListBoxItemの"Visibility"とバインドされている。 1. 「東日本」をクリックする 2. "SelectedItemChanged"イベントが発生 3. "一覧"の中から"ノードパス"が「日本ー東日本」と一致もしくは「日本ー東日本」を含んでいるアイテムを探す 4. 条件が合うアイテムの"表示"プロパティを"Visible"、それ以外は"Collapsed"をsetする

発生している問題・エラーメッセージ

ただ、実際のアプリケーションではリストの全アイテム数が最大で10000件になる予定で、
3000件ほどで、ツリーを遷移したときにStackoverflow Exceptionが発生してしまっています。
(なおイベントを抜けた後の処理で発生しているようで、具体的な箇所については特定できてません。)

また件数が10件程度でも
・スクロールバーの挙動(サイズやスクロール時の)がおかしい
・ListBoxItemのVisibilityCollapsedを設定した項目が、実際にはHiddenの動きになっている(空白にはなっているもののItemの領域が存在しているため、謎の空白の空間が生まれる)
・以下のバインディングエラーが起きる

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null; target element is 'ListBoxItem' (Name=''); target property is 'HorizontalContentAlignment' (type 'HorizontalAlignment')

など様々な問題が発生しており、そもそも根本的な実装が間違えているのかと思いました。

質問

上記のような機能を実装する場合、どのように実装するのがベストでしょうか?

各地域ごとに都道府県のリスト(一覧リスト)を持たせることも考えましたが、実アプリケーションではリアルタイムにリストのコンテンツが変動する点(同期の問題)や
例えば「東京」が含むツリーを考えると「日本」「東日本」「関東」すべてのリストに含ませる必要がある点から、非現実的だと思っています。

補足

ひとまず上記のバインディングエラーと謎の空白の空間については、
・StyleのVerticalAlignmentHorizontalAlignmentを明示的に設定する
VisibilityCollapsedのときにMargin=0にするトリガーを設定する
などを試しましたが解決には至りませんでした。

あまりソースを出したくないのでわかりにくい説明だとは思いますが、ご助言頂けますと幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hihijiji

2019/05/15 09:32

Stackoverflow が出るなら大概バグだと思います。 再帰処理とか書いてるならその辺を疑ってみてください。
draq

2019/05/15 13:15

そもそも地域で県をフィルタした結果をListBoxにバインドした方がいい気がします。
siksmtt

2019/05/16 00:29

hihijiji 様 ListBoxに関わるところでは再帰処理は記述していない上、TreeViewをOFFにした状態でも発生しているので、再帰処理は問題ないと思っています。 またコードビハインドに記述したノード選択遷移イベント("SelectedItemChanged"イベント)を抜けた後でエラーが発生してしまっているので、具体的な箇所が掴めていない状況になっています...。
siksmtt

2019/05/16 00:30

draq 様 地域毎にフィルタした結果のListを持たせるということでしょうか?
draq

2019/05/16 07:11

そうです。ViewModelで完結することをViewのコードビハインドで処理するのは個人的に気持ち悪いです。 バインドする県リストに本来必要の無いデータが多すぎるのもパフォーマンスに悪影響ありそうですし。
siksmtt

2019/05/16 08:33

draq 様 ご指摘ありがとうございます。色々調査しても解決の糸口が見えなかったので、ご提案の方法で試したところとりあえず各地域の遷移時の動作は理想の形になりました。 質問文にもあるように、実際のアプリケーションではリアルタイムにコンテンツが変動するので、そちらも確認しますが ひとまずご提案の方法でテスト実装してみようと思います。
guest

回答2

0

自己解決

draq様にご指摘いただいた
「そもそも地域で県をフィルタした結果をListBoxにバインドした方がいい気がします。」
こちらの方法で実装したところ、理想の動きになりました。

BAさせていただきたいところですが、自分が失念していたせいもあり時間が経ってしまったので自己解決とさせていただきます。
ありがとうございました。

投稿2019/07/17 06:04

siksmtt

総合スコア20

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

投稿2019/05/15 08:31

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

siksmtt

2019/05/16 00:26

Zuishin 様 ご回答ありがとうございます。 ListBoxについては既に仮想化を行っています。仮想化OFF状態での処理負荷とON状態での動作負荷を比べたところ、明らかな負荷差が見られるので仮想化については問題なくできていると思っています。 TreeViewとの関連性も確認してみましたが、 TreeViewがない状態でもスクロールバーがおかしい現象やバインディングエラーが発生しているので、関連性としては低いと思っています。
Zuishin

2019/05/16 00:38

デバッグ依頼だったんですか? これだけの情報からは無理ですよ。 まずは Model 層と ViewModel 層のテストを作成し、考えられるあらゆるデータにおいてそれが通るようにしてください。通らないならそこに問題があるのでしょうし、通るなら View 層のデバッグをするより仕方ないでしょう。
siksmtt

2019/05/16 01:52

Zuishin 様 誤解を招く言い方になり申し訳ありません。これだけしか情報がない中で「他に考えられる可能性はありますか」と聞くのも失礼かと思い、単純にご指摘頂いた内容への回答として返信いたしました。 デバッグについては引き続き行いますが、もし代案などあればご指摘いただければ幸いです。
Zuishin

2019/05/16 01:56 編集

代案も何も今の案がわからないので何とも言えませんが、ただバグが入ってるだけのような気がします。 テストは作ってますか?
siksmtt

2019/05/16 08:30

Zuihin 様 テストを作成して発生条件などを絞ったところ、 ScrollViewer.CanContentScroll="True" を設定し、且つModelの方で Visibility=Collapsedにすると発生するようでした。 また軽くView層のテストも行ったところ、イベントを抜けた後で「循環が検出されました」というエラーが発生しており、View側の処理が永遠と走り続けるようでした。 恥ずかしながらView層のテストはほぼしたことがなくどのように進めればいいのかもまだ分かっていないのですが、 ひとまず仮想化と関わっている気がするので(仮想化OFFを避けるために)他の方法で対処しようと思います。 ひとまずご報告になります。ご指摘ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問