前提・実現したいこと
C#とWPFにてアプリを作成しております。
対象データごとに詳細データを確認、追加、編集出来るページがあるのですが、詳細データListView部分のスクロールのコントロールが上手くいかない部分があります。
対象データを変更するごとに詳細データの横スクロールを初期値(1番左)へ戻したいです。
発生している問題
詳細データを保持している対象データを表示する
↓
詳細データの横スクロールを1番右へ移動させる
↓
表示されている詳細データを削除する
↓
詳細データを保持していない対象データを表示する
↓
詳細データを追加するとスクロールが右位置のまま表示される
遷移先の対象データが詳細データを保持していればスクロールは初期値(1番左)へ戻っている
といった状態です。
該当のソースコード
C#側で対象データが変わる際に通るようScrollToHomeは実装しています。
補足情報
VisualStudio2013で実装。
調査を進めてデータがないとスクロールコントロールが出来ないように思った。
データがない場合でもスクロールをコントロール出来るよう実装したいです。
どなたかご教示お願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
下記のような質問は推奨されていません。
- 質問になっていない投稿
- スパムや攻撃的な表現を用いた投稿
適切な質問に修正を依頼しましょう。
回答1件
1
ベストアンサー
詳細データを追加するとスクロールが右位置のまま表示される
うまく日本語で説明できませんが、ListView
はItemsSource
をまたがってスクロール位置を保存しているということですよね?
なぜかアイテムが空の時に限って、水平スクロールバーも出ないし左端に寄って表示する。
そこでアイテムが追加されると、保存された位置にスクロールされる。
これ自体はちょっと変ですが標準の動作ですね。
C#側で対象データが変わる際に通るようScroll ToHomeは実装しています。
これのことでしょうか?
ScrollViewer.ScrollToHome Method (System.Windows.Controls) | Microsoft Docs
このちょっと変な動作をキャンセルするために、選択が変わるたびにScrollToHome
しているが「アイテムが空の時だけは効かない」と。
私もよくわかりませんが、これに該当するということなんでしょう。
This method does not induce any scrolling behavior if ScrollInfo is null.
単純にやるならアイテムの追加時にもScrollToHome
したらどうですか?
(確かに「位置を保存しないオプション」があってもいいですね)
今の理解での検証コード(全然違うという場合はもっと詳しく説明してください)
xaml
1<Window 2 x:Class="Questions336796.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 Width="800" 6 Height="450"> 7 <Grid> 8 <Grid.ColumnDefinitions> 9 <ColumnDefinition /> 10 <ColumnDefinition Width="Auto" /> 11 <ColumnDefinition /> 12 </Grid.ColumnDefinitions> 13 <ListBox 14 x:Name="listBox" 15 DisplayMemberPath="Name" 16 ItemsSource="{Binding Items}" 17 SelectionChanged="ListBox_SelectionChanged" /> 18 <StackPanel Grid.Column="1"> 19 <Button Click="AddButton_Click" Content="詳細追加" /> 20 <Button Click="ClearButton_Click" Content="詳細全削除" /> 21 <CheckBox 22 x:Name="checkBox1" 23 Content="ScrollToHome" 24 IsChecked="True" /> 25 <CheckBox 26 x:Name="checkBox2" 27 Content="Virtualizing" 28 IsChecked="True" /> 29 </StackPanel> 30 <ListView 31 x:Name="listView" 32 Grid.Column="2" 33 ItemsSource="{Binding SelectedItem.Details, ElementName=listBox}" 34 VirtualizingPanel.IsVirtualizing="{Binding IsChecked, ElementName=checkBox2}"> 35 <ListView.View> 36 <GridView> 37 <GridViewColumn 38 Width="200" 39 DisplayMemberBinding="{Binding Detail1}" 40 Header="詳細1" /> 41 <GridViewColumn 42 Width="200" 43 DisplayMemberBinding="{Binding Detail2}" 44 Header="詳細2" /> 45 <GridViewColumn 46 Width="200" 47 DisplayMemberBinding="{Binding Detail3}" 48 Header="詳細3" /> 49 </GridView> 50 </ListView.View> 51 </ListView> 52 </Grid> 53</Window>
C#
1using System; 2using System.Collections.Generic; 3using System.Collections.ObjectModel; 4using System.Linq; 5using System.Windows; 6using System.Windows.Controls; 7using System.Windows.Media; 8 9namespace Questions336796 10{ 11 public partial class MainWindow : Window 12 { 13 public ObservableCollection<Item> Items { get; } 14 15 public MainWindow() 16 { 17 InitializeComponent(); 18 19 Items = new ObservableCollection<Item> 20 { 21 new Item { Name = "Item1", }, 22 new Item { Name = "Item2", }, 23 new Item { Name = "Item3", }, 24 }; 25 Items[0].Details.Add(new Detail()); 26 Items[2].Details.Add(new Detail()); 27 28 DataContext = this; 29 } 30 31 private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 32 { 33 if (checkBox1.IsChecked == true) 34 { 35 var sv = listView.Descendants<ScrollViewer>().First(); 36 sv.ScrollToHome(); 37 } 38 } 39 40 private void AddButton_Click(object sender, RoutedEventArgs e) 41 { 42 if (listBox.SelectedItem is Item item) 43 item.Details.Add(new Detail()); 44 45 if (checkBox1.IsChecked == true) 46 { 47 var sv = listView.Descendants<ScrollViewer>().First(); 48 sv.ScrollToHome(); 49 } 50 } 51 52 private void ClearButton_Click(object sender, RoutedEventArgs e) 53 { 54 if (listBox.SelectedItem is Item item) 55 item.Details.Clear(); 56 } 57 } 58 59 public class Item 60 { 61 public string Name { get; set; } 62 public ObservableCollection<Detail> Details { get; } = new ObservableCollection<Detail>(); 63 } 64 65 public class Detail 66 { 67 public string Detail1 { get; set; } = "Detail1"; 68 public string Detail2 { get; set; } = "Detail2"; 69 public string Detail3 { get; set; } = "Detail3"; 70 } 71 72 // [VisualTreeの子孫要素を取得する - xin9le.net](https://blog.xin9le.net/entry/2013/10/29/222336) 73 public static class DependencyObjectExtensions 74 { 75 //--- 子要素を取得 76 public static IEnumerable<DependencyObject> Children(this DependencyObject obj) 77 { 78 if (obj == null) throw new ArgumentNullException(nameof(obj)); 79 80 var count = VisualTreeHelper.GetChildrenCount(obj); 81 if (count == 0) yield break; 82 83 for (var i = 0; i < count; i++) 84 { 85 var child = VisualTreeHelper.GetChild(obj, i); 86 if (child != null) yield return child; 87 } 88 } 89 90 //--- 子孫要素を取得 91 public static IEnumerable<DependencyObject> Descendants(this DependencyObject obj) 92 { 93 if (obj == null) throw new ArgumentNullException(nameof(obj)); 94 95 foreach (var child in obj.Children()) 96 { 97 yield return child; 98 foreach (var grandChild in child.Descendants()) 99 yield return grandChild; 100 } 101 } 102 103 //--- 特定の型の子要素を取得 104 public static IEnumerable<T> Children<T>(this DependencyObject obj) 105 where T : DependencyObject => obj.Children().OfType<T>(); 106 107 //--- 特定の型の子孫要素を取得 108 public static IEnumerable<T> Descendants<T>(this DependencyObject obj) 109 where T : DependencyObject => obj.Descendants().OfType<T>(); 110 } 111}
仮想化を切っても(回答コードで両方のチェックを外す)似たような動きになりましたが、これはちょっとイヤですかねぇ。
投稿2021/05/06 09:25
総合スコア8294
下記のような回答は推奨されていません。
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
このような回答には修正を依頼しましょう。
回答へのコメント
関連した質問
Q&A
解決済
[Xamarin.Android]ListViewの高さを、アイテム数に応じて自動調節したい
回答1
クリップ0
更新
2023/03/25
意見交換
受付中
AIによる影響についての皆様の意見に対して
回答9
クリップ1
更新
2023/03/30
Q&A
解決済
Visual Studio WPFアプリ開発で実行時コントロールの大きさや位置がおかしくなってしまう
回答1
クリップ1
更新
2023/03/13
Q&A
受付中
デシクショナリーオブジェクトを利用して、重複データを格納したい
回答7
クリップ0
更新
2023/03/29
Q&A
解決済
【Python】csvファイルを加工して5分おきのデータを0埋めしたいです。
回答2
クリップ0
更新
2023/03/30
Q&A
解決済
【GAS】フォルダ内の全ファイルに対し処理を行う際の処理順
回答1
クリップ2
更新
2023/04/01
Q&A
解決済
スマホで確認すると縦スクロール効かない
回答1
クリップ0
更新
2023/03/31
意見交換
受付中
C#によるフォームアプリ開発について
回答2
クリップ0
更新
2023/03/29