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

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

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

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

WPF

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

Q&A

解決済

2回答

1611閲覧

WPFで動的に配置したコントロールのScrollViewerを出したい

sheephuman

総合スコア112

C#

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

WPF

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

1グッド

0クリップ

投稿2023/02/11 13:31

編集2023/02/20 23:42

やりたいこと

ItemsControlを使ったコントロールの動的配置の際ScrollViewerが出ないのでなんとか出したい。

追記:この質問の趣旨ですが、WPFで動的にコントロールを追加するCodeを上手く動かす事が出来ず、ちょっと邪道だけどたまたま見つけたCodeで何とかできないか模索したものです。結果的に自己解決したのでそれも投稿しました。

個人的にアプリ開発をしています。
最近出したもの:リンク内容

実現したこと

UserControl を動的に生成して任意の座標に配置したい
上記のコードを書き換えまして、動的なコントロールの配置までは実現できました。しかしScrollViewerは出てくれません。ScrollViewerを配置して動かそうとするとControlの方が非表示になってしまいます。

追記:このリンク先のCode自体はどっちかというとTwitter上の「WPFじゃ○○が出来ない~」という声に対してokazuki氏が反応されたモノのようで、あまり通常のコントロール配置には適していないのではないかと思われます。

現状のコード(XAML)

XAML

1<Window 2 x:Class="PureWpf.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:PureWpf" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 Title="MainWindow" 9 Width="800" 10 Height="450" 11 mc:Ignorable="d"> 12 <Window.DataContext> 13 <local:MainWindowViewModel /> 14 </Window.DataContext> 15 <Grid VerticalAlignment="Top" ScrollViewer.CanContentScroll="True"> 16 <ScrollViewer VerticalScrollBarVisibility="Auto"/> 17 <Button Command="{Binding AddCommand}" Content="Add" Width="100" Height="50" /> 18 19 20 21 <ItemsControl Grid.Row="1" ItemsSource="{Binding Items}"> 22 23 <ItemsControl.ItemsPanel> 24 <!-- 要素の並びは Canvas で好きな座標に出せるようにする --> 25 <ItemsPanelTemplate> 26 27 28 <Canvas ScrollViewer.CanContentScroll="True" > 29 30 31 </Canvas> 32 33 34 </ItemsPanelTemplate> 35 36 </ItemsControl.ItemsPanel> 37 38 <ItemsControl.ItemTemplate> 39 40 <DataTemplate DataType="local:Item"> 41 <!-- ここに表示したい UserControl を設定する。今回は別途作るのがめんどいので WPF のコントロールを直接並べてます --> 42 <local:ParaSelector 43 Width="400" 44 Height="50" 45 Margin="10,-20,280,640" 46 > 47 48 </local:ParaSelector> 49 </DataTemplate> 50 </ItemsControl.ItemTemplate> 51 <ItemsControl.ItemContainerStyle> 52 <!-- Canvas 上での表示位置の設定は Canvas に直接乗るコンテナに指定 --> 53 <Style TargetType="ContentPresenter"> 54 <Setter Property="Canvas.Top" Value="{Binding Y}" /> 55 <Setter Property="Canvas.Left" Value="{Binding X}" /> 56 </Style> 57 </ItemsControl.ItemContainerStyle> 58 </ItemsControl> 59 60 61 62 </Grid> 63 64</Window> 65

コードビハインド(CS)

CS

1using Prism.Commands; 2using Prism.Mvvm; 3using System; 4using System.Collections.ObjectModel; 5 6namespace PureWpf 7{ 8 public class MainWindowViewModel : BindableBase 9 { 10 11 public ObservableCollection<Item> Items { get; } = new(); 12 13 private DelegateCommand _addCommand; 14 public DelegateCommand AddCommand => _addCommand ??= new(AddExecute); 15 16 int TOPCh =0; 17 int LeftCh = 0; 18 // 表示位置をランダムにするための Random クラス 19 private Random Random { get; } = new(); 20 private void AddExecute() 21 { 22 // ランダムな位置に、とりあえず現在時間の文字列を出すようなデータを作る 23 24 for (int i = 3; i > 0; i--) 25 { 26 Items.Add(new(TOPCh =0 , LeftCh+=30)); 27 } 28 29 30 } 31 32 } 33} 34 35

出力結果

イメージ説明
見切れたときにScrollViewerが出てくれないと困るので何か方法をご教授願います。
前提条件として自作のカスタムコントロールを使用しています。

XAML

1<UserControl x:Class="PureWpf.ParaSelector" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:PureWpf" 7 mc:Ignorable="d" 8 d:DesignHeight="450" d:DesignWidth="800"> 9 <Grid> 10 11 <TextBox x:Name="ArgumentEditor" Margin="100,3,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="380"/> 12 13 <RadioButton 14 GroupName="SelectorGroup" Content="" Name="SlectorRadio" HorizontalAlignment="Left" Margin="0,5,0,0" VerticalAlignment="Top"/> 15 16 17 <ContentControl Name="SelectorLabelCon"> 18 <TextBlock 19 Name="ParamLabel" 20 TextWrapping="Wrap" 21 Width="80" 22 23 HorizontalAlignment="Left" 24 Text="パラメータ名" Margin="15,3,0,0"/> 25 </ContentControl> 26 </Grid> 27</UserControl> 28

試したこと

https://stackoverflow-com.translate.goog/questions/2028459/wpf-itemscontrol-with-scrollbar-scrollviewer?_x_tr_sl=en&_x_tr_tl=ja&_x_tr_hl=ja&_x_tr_pto=sc の2番目の回答などは試しました。既存のXAMLに組み込む形で試したものの、コントロールが追加されませんでした(実際は追加されているがホストされたコントロールにより非表示になっている)。

ItemsControl.ItemsPaneを <ItemsControl.Template>に置き換えるなどしました。

XAML

1<Window 2 x:Class="PureWpf.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 6 xmlns:local="clr-namespace:PureWpf" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 Title="MainWindow" 9 Width="800" 10 Height="450" 11 mc:Ignorable="d"> 12 <Window.DataContext> 13 <local:MainWindowViewModel /> 14 </Window.DataContext> 15 <Grid VerticalAlignment="Top" ScrollViewer.CanContentScroll="True"> 16 <ScrollViewer VerticalScrollBarVisibility="Auto"/> 17 <Button Command="{Binding AddCommand}" Content="Add" Width="100" Height="50" /> 18 19 20 21 <ItemsControl Grid.Row="1" ItemsSource="{Binding Items}"> 22 23 24 <ItemsControl.Template> 25 <!-- 要素の並びは Canvas で好きな座標に出せるようにする --> 26 <ControlTemplate> 27 28 <ScrollViewer> 29 <Canvas/> 30 </ScrollViewer> 31 32 33 34 </ControlTemplate> 35 36 </ItemsControl.Template> 37 38 <ItemsControl.ItemTemplate> 39 40 <DataTemplate DataType="local:Item"> 41 <!-- ここに表示したい UserControl を設定する。今回は別途作るのがめんどいので WPF のコントロールを直接並べてます --> 42 <local:ParaSelector 43 Width="400" 44 Height="50" 45 Margin="10,-20,280,640" 46 > 47 48 </local:ParaSelector> 49 </DataTemplate> 50 </ItemsControl.ItemTemplate> 51 <ItemsControl.ItemContainerStyle> 52 <!-- Canvas 上での表示位置の設定は Canvas に直接乗るコンテナに指定 --> 53 <Style TargetType="ContentPresenter"> 54 <Setter Property="Canvas.Top" Value="{Binding Y}" /> 55 <Setter Property="Canvas.Left" Value="{Binding X}" /> 56 </Style> 57 </ItemsControl.ItemContainerStyle> 58 59 </ItemsControl> 60 61 62 63 </Grid> 64 65</Window> 66

補足情報(FW/ツールのバージョンなど)

Visual Studio 2022を使用しています。.net7で開発しています。

TN8001👍を押しています

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

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

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

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

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

guest

回答2

1

ベストアンサー

Canvasはほかのパネルとだいぶ動作が異なります。

例えばStackPanelはアイテムが追加されると、縦にサイズが伸びていきますね?
Canvasは任意の場所に追加できるためか、アイテムを追加してもサイズを変えません。
「ライブ プロパティ エクスプローラー」で、CanvasActualWidthActualHeightを確認してみてください。
デバッグ中に XAML のプロパティを調べる - Visual Studio (Windows) | Microsoft Learn

なのでCanvasのサイズを入れてあげればいいということです。
WPFで、Canvasコントローラにスクロールを追加したい

xml

1<Window 2 x:Class="Qispujgfsvspc6p.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="clr-namespace:Qispujgfsvspc6p" 6 Width="800" 7 Height="450"> 8 <Window.DataContext> 9 <local:MainWindowViewModel /> 10 </Window.DataContext> 11 <Grid> 12 <Grid.RowDefinitions> 13 <RowDefinition Height="Auto" /> 14 <RowDefinition /> 15 </Grid.RowDefinitions> 16 <Button 17 MinHeight="50" 18 Command="{Binding AddCommand}" 19 Content="Add" /> 20 21 <ItemsControl Grid.Row="1" ItemsSource="{Binding Items}"> 22 23 <!-- ItemsControl自体のテンプレート --> 24 <ItemsControl.Template> 25 <ControlTemplate> 26 <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> 27 <ItemsPresenter HorizontalAlignment="Left" VerticalAlignment="Top" /> 28 </ScrollViewer> 29 </ControlTemplate> 30 </ItemsControl.Template> 31 32 <ItemsControl.ItemsPanel> 33 <ItemsPanelTemplate> 34 <!-- Canvasのサイズを入れないとスクロールバーを出せない --> 35 <Canvas Width="{Binding CanvasWidth}" Height="{Binding CanvasHeight}" /> 36 </ItemsPanelTemplate> 37 </ItemsControl.ItemsPanel> 38 39 <ItemsControl.ItemContainerStyle> 40 <Style TargetType="ContentPresenter"> 41 <Setter Property="Canvas.Top" Value="{Binding Y}" /> 42 <Setter Property="Canvas.Left" Value="{Binding X}" /> 43 </Style> 44 </ItemsControl.ItemContainerStyle> 45 46 <ItemsControl.ItemTemplate> 47 <DataTemplate DataType="local:Item"> 48 <local:ParaSelector Width="400" Height="50" /> 49 </DataTemplate> 50 </ItemsControl.ItemTemplate> 51 </ItemsControl> 52 </Grid> 53</Window>

cs

1using System.Collections.ObjectModel; 2using System.Linq; 3using System.Windows; 4using CommunityToolkit.Mvvm.ComponentModel; 5using CommunityToolkit.Mvvm.Input; 6 7namespace Qispujgfsvspc6p; 8 9 10public record Item(int X, int Y); 11 12public partial class MainWindowViewModel : ObservableObject 13{ 14 public ObservableCollection<Item> Items { get; } = new(); 15 16 [ObservableProperty] 17 private double _CanvasWidth; 18 19 [ObservableProperty] 20 private double _CanvasHeight; 21 22 23 private int TOPCh = 0; 24 private int LeftCh = 0; 25 26 [RelayCommand] 27 private void Add() 28 { 29 for (int i = 3; i > 0; i--) 30 { 31 Items.Add(new(TOPCh = 0, LeftCh += 30)); 32 } 33 34 // + 400, + 50 の根拠 <local:ParaSelector Width="400" Height="50" /> 35 CanvasWidth = Items.Max(x => x.X + 400); 36 CanvasHeight = Items.Max(x => x.Y + 50); 37 } 38} 39 40public partial class MainWindow : Window 41{ 42 public MainWindow() => InitializeComponent(); 43}

NuGet Gallery | CommunityToolkit.Mvvm 8.1.0
MVVM ソース ジェネレーター - .NET Community Toolkit | Microsoft Learn


実際の用途がわかりませんが、縦に並べるだけならCanvasを使うべきではないです(本当に任意の位置に出したいならそうせざるを得ませんが)

Marginで位置合わせするような作り(ParaSelector)はよくありません(ユーザーのフォント設定等で簡単に崩れます)
面倒でもColumnDefinitionで区切り、サイズを合わせたい場合はSharedSizeGroupで対応してください。
方法: グリッド間でサイズ設定プロパティを共有する - WPF .NET Framework | Microsoft Learn

Window以外の)WidthHeightも固定値で入れるべきではないです。

ですが、実際の作りがわからないのでParaSelectorはそのままで手元の実行結果。
アプリ画像

投稿2023/02/11 15:53

編集2023/02/11 15:56
TN8001

総合スコア9190

sheephuman❤️を押しています

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

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

sheephuman

2023/02/18 07:12

自分のCode弄っていたら出来てしまったので結果的に使いませんでした。 ご指摘の通り頻繁にコントロールの位置が崩れてしまうのでSharedSizeGroupで設定する必要があるのですね。 PC毎の解像度の設定に依っても表示崩れが発生してしまうのでしょうか。
TN8001

2023/02/18 07:57

> PC毎の解像度の設定に依っても表示崩れが発生してしまうのでしょうか。 高DPIは詳しくないんですが、基本的には崩れはないという認識です(ぼやけたりはする) 中途半端な対応だと崩れたりするのかもしれません(やるならきっちりやる・やらないなら一切いじらない) [Windowsでの高 DPI デスクトップ アプリケーション開発 - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows) [wpf per monitor v2 - Google 検索](https://www.google.com/search?q=wpf+per+monitor+v2) > 自分のPCだけで正常に表示されても意味がないので、今後はColumnDefinitionを使用した設定方法を模索してみます。 自分用なら細かいことを言う気はないんですが、配布されているようなので細かく突っ込んでしまいました(気分を害されていたらすいません^^;
sheephuman

2023/02/18 10:01

特に業務的な事はしないので基本的な知識を持っていません。 むしろそういう定石みたいなのをもっと知っておきたいです。妙な我流を身に着けると応用が利かないので
TN8001

2023/02/18 11:38

> 特に業務的な事はしないので基本的な知識を持っていません。 わたしもアマチュアで独学なので、これといって良いアドバイスができるわけでもないです^^; WPFの書籍も1冊も持っていません(「欲しいな」とは思いますが古いですし高いので^^; レイアウトに細かいのは、(視力的な意味で)システムフォントをいじっているためです(デフォルトは游ゴ9ptだと思いますが、メイリオ12ptにしています) [Meiryo UIも大っきらい!!の詳細情報 : Vector ソフトを探す!](https://www.vector.co.jp/soft/winnt/util/se500183.html) フリーソフトなんかでも、文字が見切れるようなものが散見されますね。 システムフォント変更・DPI変更等しっかりテストできればいいのですが、面倒なのでなかなか悩ましいですよね... > むしろそういう定石みたいなのをもっと知っておきたいです。 デザインガイドラインみたいなのは公式だとこのあたりでしょうか。 Win32用(旧) [ガイドライン - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/uxguide/guidelines) UWP(WinUI)用 [Windows アプリの設計とコーディング - Windows apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/apps/design/) C#一般 [フレームワーク デザインのガイドライン | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/standard/design-guidelines/) 設定画面なんかは最近のWindowsでは、ダイアログでなくウィンドウ内で変更するものが多くなっていますよね。 箇条書き風にだらだらスクロールするような奴(使いやすいかは何とも言えないが^^; [アプリ設定のガイドライン - Windows apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/apps/design/app-settings/guidelines-for-app-settings) あとWinUIのサンプルを見たりして「なるほどこういうのが今風なのね~」って参考にしたりはします(現時点のWinUIは「あれがない・これもない」でイライラするので勧めはしませんw [WinUI 3 Gallery - Microsoft Store アプリ](https://apps.microsoft.com/store/detail/winui-3-gallery/9P3JFPWWDZRC?hl=ja-jp&gl=jp) [Windows Community Toolkit Sample App - Microsoft Store アプリ](https://apps.microsoft.com/store/detail/windows-community-toolkit-sample-app/9NBLGGH4TLCQ?hl=ja-jp&gl=jp)
sheephuman

2023/02/19 09:30

色々とありがとうございます。自分で調べ出すとキリがなくなるのでありがたいです。 デザイン設定で分からなくなったら読もうと思います。
sheephuman

2023/02/21 00:01

個人的にはデザインの定石というよりCodingの定石を知りたいだけなのです。 UIは既存のものを改良するカタチを志向しています。実を言うとそんな勉強家ではないからいちいちそんな長いモノは読まないので.... 開発の上でシステムUIのフォントサイズを弄られる事までは想定してないので、こちらでも検証した上で、TN8001 さんはアプリを幾つか挙げてらっしゃるのでそちらでは対策としてどうしているのか回答依頼を出す事になるかと思います。ちょっとばかり気になっています。
TN8001

2023/02/21 03:46

> 個人的にはデザインの定石というよりCodingの定石を知りたいだけなのです。 なんとなく話がかみ合わなくなってきている気がします。 わたしの回答の趣旨は * Canvasを使うべきではないんじゃないか * <local:ParaSelector Width="400" Height="50" Margin="10,-20,280,640">のようなのはまずい です。 表題を回収するためにCanvasでやりましたが、sheephumanさんの回答を見る限りStackPanelに戻したってことですよね? Heightを明示的に入れないことで、内容の長さ?によって高さが可変になっていますよね。 (このウィンドウはサイズ固定かもしれませんが)Widthも入れなければウィンドウサイズによって、折り返し位置も自動で変わるようになるはずです。 要は固定値を極力入れないようにして、レイアウトに任せるようにするってことです。 まあまったく入れないわけにもなかなかいきませんが、MinMaxや割合指定(1*,2*)・ダミーのコントロールの大きさを参照する等々やりようはあります(これを「定石」とおっしゃっている??) > システムUIのフォントサイズを弄られる事までは想定してない システムフォントに限らず、多言語化とかでも内容のサイズは変わりますよね?(多言語化する気はないかもしれませんが) あるいはくだんの設定画面のように、ユーザー入力によってサイズが変わることもあるわけです(そして見切れたりしていないわけですから、そこは対策できていることになるはずです) > アプリを幾つか挙げてらっしゃるのでそちらでは対策としてどうしているのか 特に対策はしていないと思います。 ウィンドウサイズの変更で中身もちゃんとついてくるように作っていれば、それが自然と対策になっていると言うか(理屈上は)問題は出ないはずです。
guest

0

動的にコントロールを追加するだけならこれでOKでした。
なんでうまく行かなったのかは忘れました。

C#

1 2 Thickness marthick = new Thickness(0,50,0,5); 3 SelectParamerterBox sbx = new SelectParamerterBox() 4 { 5 Margin = marthick, 6 FontSize = 14, 7 Width= 480, 8 9 }; 10 11 for (int SelectorGenerate = 10 ;SelectorGenerate > 0 ; SelectorGenerate--) 12 { 13 SelectorStack.Children.Add(new SelectParamerterBox());

自作アプリでの適用例
イメージ説明

自分のPCだけで正常に表示されても意味がないので、今後はColumnDefinitionを使用した設定方法を模索してみます。

投稿2023/02/18 07:22

sheephuman

総合スコア112

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.54%

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

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

質問する

同じタグがついた質問を見る

C#

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

WPF

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