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

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

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

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

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

MVVM

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

WPF

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

Q&A

解決済

1回答

5971閲覧

Canvasコントロールの子要素を動的に増減させたい

tails

総合スコア22

canvas

HTML5の<canvas>要素用のタグです。CanvasはHTML5から導入された、二次元の図形描写が可能な要素です。

.NET Core

.NET Coreは、マネージソフトウェアフレームワークでオープンソースで実装されています。クロスプラットフォームを前提に考えられており、Windows/Mac/Linuxで動くアプリケーションを作成することが可能です。

C#

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

MVVM

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

WPF

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

1グッド

0クリップ

投稿2021/09/15 14:07

やりたいこと

MVVM下で、WPF & C# を使って、Canvas コントロールの子要素を動的に増減させたいです。
こちらにある質問と同様の質問になりますが、子要素は (そちらの質問がやっているような) Rectangle だけでなく、Canvas の子要素にすることができる全てのコントロールを対象として増減させたいです。

質問

このようなことが可能であれば、やり方を教えてください。
ViewModel にバインドする方法で出来なければ、Canvas.Children.Add でやりますので、可能でない場合は、可能でない、と教えていただけるだけで大丈夫です。

自分のレベル

C, C++, JavaScript は10年ほど
C# は3ヵ月ほど
.NET Core 3.1 & WPFは、1日経った程度です。
よって、C#は大体分かりますが、WPFはまだあまりよく分かっていません。
最低限、MSDocsのWPF入門は一通り見ており、基礎的なウィンドウ程度は作れます。
Binding, DataContext を使った View-ViewModel 間のデータバインドの方法も、単純なものなら理解しています。

TN8001👍を押しています

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

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

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

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

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

TN8001

2021/09/16 11:17

> Canvas の子要素にすることができる全てのコントロールを対象として増減させたいです。 理屈上はChildrenにはUIElementなら何でも入りそうですが、入れても意味のないものもありそうですし実際は「自分で選んだいくつかのコントロール」ではないのですか? [C# - C#、WPF、MVVM形式、で画面に図形を表示したい|teratail](https://teratail.com/questions/349407#reply-478878 例えば↑のようにDataTemplate・classを必要なだけ増やすのは、できたことになるんですか? あるいは型名やTypeからインスタンスを作ること自体は容易ですが、できたところで型に固有のプロパティ(RectangleならFill・ButtonならContent・TextBlockならText等々)をどう設定するのですか?
tails

2021/09/16 16:04

ご回答ありがとうございます。 確かに、実際は「自分で選んだいくつかのコントロール」ですね。 Path, Ellipse, Image, Rectangle, RichTextBox が今のところ想定しているコントロールです(が後々、増減える可能性があります)。 PDFリーダを作りたくて、それの実装に必要なコントロールたちですね。 PDFの各ページを Canvas にして、そこに描画する形での実装を考えています。 参考先のリンクも拝見しました。 > 例えば↑のようにDataTemplate・classを必要なだけ増やす DataTemplate をクラスごとに出来るんですね。 確かに、その方法で、プロパティも設定できるなら、必要な分だけ追加するのでも十分そうです。 > 型に固有のプロパティ ... をどう設定する Canvas.Children.Add でやる場合の話でしょうか? その場合は、 var rectangle = new System.Windows.Shapes.Rectangle(); rectangle.Fill = System.Windows.Media.Brushes.White; のように設定して、Canvas.Children.Add(rectangle); のイメージでした。 そうじゃなくて、バインドする形でやる場合は、、 参考先リンクのご回答の Shapes にバインドさせて、そこにプロパティ付きの Diamond, Circle などを追加し、View からは、バインドされている Shapes から Shape 型のオブジェクトが取れるわけですが、「その元の型」(つまり、Diamond or Circle) を取り出して、元の型ごとに分岐させて、そこからプロパティを取れるような感じにできないかな と思っています。 参考先リンクのご回答の DataTemplate で、{x:Type local:Diamond} で指定しているのって、そういうことですよね? この Diamond クラスにプロパティを持たせれば、できそうな感じがしています。
guest

回答1

0

ベストアンサー

C# - C#、WPF、MVVM形式、で画面に図形を表示したい|teratail
例えば↑のようにDataTemplate・classを必要なだけ増やす

DataTemplate をクラスごとに出来るんですね。
確かに、その方法で、プロパティも設定できるなら、必要な分だけ追加するのでも十分そうです。

提示リンクとほぼ何も変わりませんが、雑に想定コントロール版に書き換えました(不足プロパティがあるでしょうが好きに足してください)
面倒なので増減はしませんが、Itemsを増減すれば表示も追従します。

PDFリーダーにこの(ItemsControlにバインドするような)方法が向いているかは、ちょっとわからないです。

xml

1<Window 2 x:Class="Questions359699.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:Questions359699" 6 Width="800" 7 Height="450"> 8 <Window.Resources> 9 <DataTemplate DataType="{x:Type local:PathItem}"> 10 <Path 11 Width="{Binding Width}" 12 Height="{Binding Height}" 13 Data="{Binding Data}" 14 Stroke="{Binding Stroke}" /> 15 </DataTemplate> 16 <DataTemplate DataType="{x:Type local:EllipseItem}"> 17 <Ellipse 18 Width="{Binding Width}" 19 Height="{Binding Height}" 20 Fill="{Binding Fill}" /> 21 </DataTemplate> 22 <DataTemplate DataType="{x:Type local:ImageItem}"> 23 <Image 24 Width="{Binding Width}" 25 Height="{Binding Height}" 26 Source="{Binding Source}" /> 27 </DataTemplate> 28 <DataTemplate DataType="{x:Type local:RectangleItem}"> 29 <Rectangle 30 Width="{Binding Width}" 31 Height="{Binding Height}" 32 Fill="{Binding Fill}" /> 33 </DataTemplate> 34 <DataTemplate DataType="{x:Type local:RichTextBoxItem}"> 35 <RichTextBox Width="{Binding Width}" Height="{Binding Height}"> 36 <FlowDocument> 37 <Paragraph> 38 <Run Text="{Binding Text}" /> 39 </Paragraph> 40 </FlowDocument> 41 </RichTextBox> 42 </DataTemplate> 43 </Window.Resources> 44 45 <Grid> 46 <ItemsControl ItemsSource="{Binding Items}"> 47 <ItemsControl.ItemsPanel> 48 <ItemsPanelTemplate> 49 <Canvas /> 50 </ItemsPanelTemplate> 51 </ItemsControl.ItemsPanel> 52 <ItemsControl.ItemContainerStyle> 53 <Style> 54 <Setter Property="Canvas.Left" Value="{Binding X}" /> 55 <Setter Property="Canvas.Top" Value="{Binding Y}" /> 56 </Style> 57 </ItemsControl.ItemContainerStyle> 58 </ItemsControl> 59 </Grid> 60</Window>

cs

1using System; 2using System.Collections.ObjectModel; 3using System.Windows; 4using System.Windows.Media; 5using System.Windows.Media.Imaging; 6 7namespace Questions359699 8{ 9 public class Item 10 { 11 public double X { get; set; } 12 public double Y { get; set; } 13 public double Width { get; set; } 14 public double Height { get; set; } 15 } 16 17 public class PathItem : Item 18 { 19 public Brush Stroke { get; set; } 20 public string Data { get; set; } 21 } 22 23 public class EllipseItem : Item 24 { 25 public Brush Fill { get; set; } 26 } 27 28 public class ImageItem : Item 29 { 30 public ImageSource Source { get; set; } 31 } 32 33 public class RectangleItem : Item 34 { 35 public Brush Fill { get; set; } 36 } 37 38 public class RichTextBoxItem : Item 39 { 40 public string Text { get; set; } 41 } 42 43 public partial class MainWindow : Window 44 { 45 public ObservableCollection<Item> Items { get; } 46 47 public MainWindow() 48 { 49 InitializeComponent(); 50 DataContext = this; 51 52 Items = new ObservableCollection<Item> 53 { 54 new PathItem { X = 50, Y = 50, Width = 50, Height = 50, Stroke = Brushes.Red, Data = "M0,25L25,50L50,25L25,0Z", }, 55 new EllipseItem { X = 200, Y = 50, Width = 50, Height = 100, Fill = Brushes.Green, }, 56 new ImageItem { X = 50, Y = 200, Width = 32, Height = 32, Source = new BitmapImage(new Uri("https://teratail-v2.storage.googleapis.com/uploads/avatars/u13/132786/KnkDDC5A_thumbnail_32x32.jpg")), }, 57 new RectangleItem { X = 200, Y = 200, Width = 100, Height = 50, Fill = Brushes.Blue, }, 58 new RichTextBoxItem { X = 400, Y = 50, Width = 300, Height = 300, Text = "RichTextBoxItem" }, 59 }; 60 } 61 } 62}

アプリ画像

投稿2021/09/16 22:11

編集2023/07/29 05:35
TN8001

総合スコア9246

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

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

tails

2021/09/17 13:27

無事、想定する感じでできました! ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問