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

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

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

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

MVVM

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

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

WPF

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

Q&A

解決済

1回答

5869閲覧

C#、WPF、MVVM形式、で画面に図形を表示したい

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

MVVM

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

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

WPF

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

0グッド

1クリップ

投稿2021/07/14 06:08

編集2021/09/13 11:38

前提・実現したいこと

ボタンを押したら多角形の図形をWPFのimage上に表示したいと考えております
ネット上を「c# WPF MVVM 図形」等のキーワードで探したのですが
これという内容見つけられませんでした。
画像表示と同じ手法でBitmapに描画したデータを代入すれば
可能と考えたのですが、うまく行きませんでした。
(https://teratail.com/questions/349227?nli=60ed5468-1ed8-4b74-8894-4a3c0a040114#reply-478633)
MVVM形式での多角形の図形表示について参考になるページ、
アドバイス等よろしくお願いします。
環境: Win10 、VS2019、C#
フレームワーク:Prism、ReactiveProperty

MainWindow.xaml

<Window x:Class="DrawCircle.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" prism:ViewModelLocator.AutoWireViewModel="True" Title="{Binding Title}" Height="400" Width="500" WindowStartupLocation="CenterScreen"> <Grid> <StackPanel> <Button Content="画像表示" Command="{Binding ImageDispLayButton}" /> <Image Stretch="None" Source="{Binding Bitmap2.Value}" Height="381" Width="496" /> <ContentControl prism:RegionManager.RegionName="ContentRegion" /> </StackPanel> </Grid> </Window>

MainWindowViewModel.cs

using Prism.Mvvm; using System.Windows; using Reactive.Bindings; using System.Windows.Media.Imaging; using System; using Prism.Commands; using System.Drawing; namespace DrawCircle.ViewModels { public class MainWindowViewModel : BindableBase { public ReactiveProperty<Bitmap> Bitmap2 { get; } = new ReactiveProperty<Bitmap>(); public ReactiveCommand ImageDispLayButton { get; } = new ReactiveCommand(); public MainWindowViewModel() { //ReactiveCommandの宣言 ImageDispLayButton.Subscribe(ImageDispLayButtonExe); } /// <summary> /// ボタン押下で任意の画像を表示する /// </summary> private void ImageDispLayButtonExe() { //図形表示 Bitmap canvas = new Bitmap(200, 200); Graphics g = Graphics.FromImage(canvas); g.FillRectangle(Brushes.Black, 10, 20, 100, 80); Bitmap2.Value = canvas; MessageBox.Show("図形描画"); g.Dispose(); } } }

試したこと

非MVVMでの図形描画ならGridの子要素にAddする形で図形をWPFに
表示できることは確認済です。
imageコントロールに図形描画をすること自体、考え違いを
しているのでしょうか?

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

環境: Win10 、VS2019、C#
フレームワーク:Prism、ReactiveProperty

2021/07/15 追記

コメント欄に書いていたソースをこちらにの追加
実現したいことは MainWindow.xaml.cs に実装している MenuItem7_Click() の多角形描画処理を
MVVM化して描画させたいと思っています

実装に際しての不明点

どのようにコーディングすればWPF側に図を表示できるのかわからない状態です。
今の私の理解では、JPG画像のようにImageにセットすればよいのか、追記したサンプルコードのように
子要素の追加すればよいのか、よく理解できていません。

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="500" Width="700"> <Grid> <StackPanel Name="StackPanel1" VerticalAlignment="Top" Orientation="Horizontal"> <Menu Height="23" Name="Menu1"> <MenuItem Header="TEST項目" Name="MenuItem1"> <MenuItem Header="クリア" Name="MenuItem0" Click="MenuItem0_Click"/> <MenuItem Header="サンプル多角形" Name="MenuItem7" Click="MenuItem7_Click"/> </MenuItem> </Menu> </StackPanel> <Grid Name="Grid1"> </Grid> </Grid> </Window>

MainWindow.xaml.cs

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void MenuItem0_Click(object sender, RoutedEventArgs e) { Grid1.Children.Clear(); ////描画領域の初期化 } /// <summary> /// 多角形描画 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MenuItem7_Click(object sender, RoutedEventArgs e) { Path myPath5 = new Path(); myPath5.Stroke = Brushes.Black; ////ブラシ色 myPath5.Fill = Brushes.RoyalBlue; ////塗りつぶし色 myPath5.StrokeThickness = 1; ////ブラシ太さ設定 PathFigure myPathFigure = new PathFigure(); ////ひし形を描画 myPathFigure.StartPoint = new Point(100, 80); ////描画の開始座標 myPathFigure.Segments.Add(new LineSegment(new Point(150, 130), true)); myPathFigure.Segments.Add(new LineSegment(new Point(100, 180), true)); myPathFigure.Segments.Add(new LineSegment(new Point(50, 130), true)); myPathFigure.Segments.Add(new LineSegment(new Point(100, 80), true)); PathGeometry myPathGeometry = new PathGeometry(); myPathGeometry.Figures.Add(myPathFigure); myPath5.Data = myPathGeometry; Grid1.Children.Add(myPath5); } } }

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

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

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

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

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

BluOxy

2021/09/09 10:51

回答がついていない質問は百歩譲るとして、この質問のように既に回答がつきクローズしている質問の内容を抹消するのは勝手ではないでしょうか。情報資産が目に触れにくくなることで回答者の努力が無駄になりますから失礼です。
guest

回答1

0

ベストアンサー

まずBitmap クラス (System.Drawing) | Microsoft Docs は、Windows Formsのクラスなので基本的にはWPFで使えません(使う方法はありますが)

Windows FormsではGDI/GDI+での描画でしたが、WPFではDirect3Dでの描画ということで根本的な部分から違っています。
グラフィックス レンダリングの概要 - WPF .NET Framework | Microsoft Docs

図形と基本描画の概要 - WPF .NET Framework | Microsoft Docs

第9回 WPFの「グラフィックス」を学ぼう:連載:WPF入門(1/2 ページ) - @IT

非MVVMでの図形描画ならGridの子要素にAddする形で図形をWPFに
表示できることは確認済です。

これは何をAddしたのでしょうか?
非MVVMでやったことのほうを提示していただいて、「それをMVVMで実現するアプローチ」を質問されたほうが回答しやすいかもしれません(あまりに複雑だと読む気がせず、回答がつかない可能性はあります^^;

imageコントロールに図形描画をすること自体、考え違いを
しているのでしょうか?

WriteableBitmap クラス (System.Windows.Media.Imaging) | Microsoft Docs
とかもあるにはありますが、カジュアルには描けません。

画面に描画でなく画像ファイルを出力したいときに、Windows Forms的にサクッと描きたいなら↓こういったライブラリはあります。
NuGet Gallery | WriteableBitmapEx 1.6.7
reneschulte/WriteableBitmapEx: Collection of extension methods for the XAML WriteableBitmap


MVVMに強いこだわりがあるようですが、あくまで手法のひとつであり必ず使わなければならないわけではありません。
小規模のアプリではメリットもあまりありません。

もちろんWPFを使う上でMVVMは大きな武器ですので、最終的にはそうあるべきだろうとは思います。

「勉強のために知りたい」・「具体例を見てみたい」とかならコードを出すこと自体は全然かまわない(回答の動機が「コードを書きたい」なので)のですが、どうしてもコード量が増えますし、内容も少し高度になってしまいます。

そういったちょっと気合を入れた回答は、(質問者がドン引きするのか)なぜか反応が芳しくないのです^^;

C# - 【WPF】Dictonaryの値をコンボボックスに表示できない、クラスを参照したい|teratail


MVVMにするアプローチの一例です(↑の回答の使いまわし^^;
MVVM的には非常に正しいと思うのですが、実際作りこむならShapePathのコレクションを持つほうが楽だと思います(提示しておいてなんですが^^;
Shape クラス (System.Windows.Shapes) | Microsoft Docs
Path クラス (System.Windows.Shapes) | Microsoft Docs

動かすのがちょっと面倒だったので、雑にMouseDragElementBehaviorを使いました(DataTemplateGridが入っているように、巧妙なごまかしがあります^^;
NuGet Gallery | Microsoft.Xaml.Behaviors.Wpf 1.1.31

xml

1<Window 2 x:Class="Questions349407.MainWindow" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:behaviors="http://schemas.microsoft.com/xaml/behaviors" 6 xmlns:local="clr-namespace:Questions349407" 7 Width="700" 8 Height="500"> 9 <Window.DataContext> 10 <local:ViewModel /> 11 </Window.DataContext> 12 <DockPanel> 13 <Menu DockPanel.Dock="Top"> 14 <MenuItem Header="ずけい"> 15 <MenuItem Command="{Binding AddDiamondCommand}" Header="ひしがた" /> 16 <MenuItem Command="{Binding AddCircleCommand}" Header="まる" /> 17 <Separator /> 18 <MenuItem Command="{Binding ClearCommand}" Header="クリア" /> 19 </MenuItem> 20 </Menu> 21 22 <ItemsControl ItemsSource="{Binding Shapes}"> 23 <ItemsControl.Resources> 24 <DataTemplate DataType="{x:Type local:Diamond}"> 25 <Grid> 26 <Path 27 Data="M100,80L150,130L100,180L50,130Z" 28 Fill="RoyalBlue" 29 Stretch="Fill" 30 Stroke="Black" 31 StrokeThickness="1"> 32 <behaviors:Interaction.Behaviors> 33 <behaviors:MouseDragElementBehavior /> 34 </behaviors:Interaction.Behaviors> 35 </Path> 36 </Grid> 37 </DataTemplate> 38 <DataTemplate DataType="{x:Type local:Circle}"> 39 <Grid> 40 <Ellipse 41 Width="100" 42 Height="100" 43 Fill="HotPink" 44 Stretch="Fill" 45 Stroke="Black" 46 StrokeThickness="1"> 47 <behaviors:Interaction.Behaviors> 48 <behaviors:MouseDragElementBehavior /> 49 </behaviors:Interaction.Behaviors> 50 </Ellipse> 51 </Grid> 52 </DataTemplate> 53 </ItemsControl.Resources> 54 <ItemsControl.ItemsPanel> 55 <ItemsPanelTemplate> 56 <Canvas /> 57 </ItemsPanelTemplate> 58 </ItemsControl.ItemsPanel> 59 </ItemsControl> 60 </DockPanel> 61</Window>

cs

1using Reactive.Bindings; 2using System.Collections.ObjectModel; 3using System.Windows; 4 5namespace Questions349407 6{ 7 public interface Shape { } // System.Windows.Shapes.Shape とは無関係 8 public class Diamond : Shape { } 9 public class Circle : Shape { } 10 public class ViewModel 11 { 12 public ObservableCollection<Shape> Shapes { get; } = new ObservableCollection<Shape>(); 13 public ReactiveCommand AddDiamondCommand { get; } = new ReactiveCommand(); 14 public ReactiveCommand AddCircleCommand { get; } = new ReactiveCommand(); 15 public ReactiveCommand ClearCommand { get; } = new ReactiveCommand(); 16 17 public ViewModel() 18 { 19 AddDiamondCommand.Subscribe(() => Shapes.Add(new Diamond())); 20 AddCircleCommand.Subscribe(() => Shapes.Add(new Circle())); 21 ClearCommand.Subscribe(() => Shapes.Clear()); 22 } 23 } 24 25 public partial class MainWindow : Window 26 { 27 public MainWindow() => InitializeComponent(); 28 } 29}

アプリ動画

投稿2021/07/14 08:56

編集2024/08/31 20:17
TN8001

総合スコア9862

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

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

退会済みユーザー

退会済みユーザー

2021/07/14 10:44

>まずBitmap クラス (System.Drawing) | Microsoft Docs は、Windows Formsのクラスなので >基本的にはWPFで使えません(使う方法はありますが) WPFとMainWindowViewModel.csのアクセスを除けば基本はC#なのでご指摘の部分を気が付きませんでした。 アドバイス頂いたリンクを確認します。 >これは何をAddしたのでしょうか? これについては以下のようなソースになります。 ### MainWindow.xaml ```ここに言語名を入力 <Window x:Class="WpfApp1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp1" mc:Ignorable="d" Title="MainWindow" Height="500" Width="700"> <Grid> <StackPanel Name="StackPanel1" VerticalAlignment="Top" Orientation="Horizontal"> <Menu Height="23" Name="Menu1"> <MenuItem Header="TEST項目" Name="MenuItem1"> <MenuItem Header="クリア" Name="MenuItem0" Click="MenuItem0_Click"/> <MenuItem Header="サンプル多角形" Name="MenuItem7" Click="MenuItem7_Click"/> </MenuItem> </Menu> </StackPanel> <Grid Name="Grid1"> </Grid> </Grid> </Window> ``` ### MainWindow.xaml.cs ```ここに言語名を入力 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WpfApp1 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void MenuItem0_Click(object sender, RoutedEventArgs e) { Grid1.Children.Clear(); ////描画領域の初期化 } /// <summary> /// 内外判定用のサンプルの多角形の形状確認 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MenuItem7_Click(object sender, RoutedEventArgs e) { Path myPath5 = new Path(); myPath5.Stroke = Brushes.Black; ////ブラシ色 myPath5.Fill = Brushes.RoyalBlue; ////塗りつぶし色 myPath5.StrokeThickness = 1; ////ブラシ太さ設定 PathFigure myPathFigure = new PathFigure(); ////ひし形を描画 myPathFigure.StartPoint = new Point(100, 80); ////描画の開始座標 myPathFigure.Segments.Add(new LineSegment(new Point(150, 130), true)); myPathFigure.Segments.Add(new LineSegment(new Point(100, 180), true)); myPathFigure.Segments.Add(new LineSegment(new Point(50, 130), true)); myPathFigure.Segments.Add(new LineSegment(new Point(100, 80), true)); PathGeometry myPathGeometry = new PathGeometry(); myPathGeometry.Figures.Add(myPathFigure); myPath5.Data = myPathGeometry; Grid1.Children.Add(myPath5); } } } ```
TN8001

2021/07/14 10:48

コメント欄のコードは読みにくいのでお手数ですが、質問に追記してください。
TN8001

2021/07/14 11:53

「MVVMにするアプローチの一例」を追記しました^^
退会済みユーザー

退会済みユーザー

2021/07/15 01:10

質問にサンプルコードを追記しました。
退会済みユーザー

退会済みユーザー

2021/07/15 04:42

>第9回 WPFの「グラフィックス」を学ぼう:連載:WPF入門(1/2 ページ) - @IT >グラフィックス レンダリングの概要 - WPF .NET Framework | Microsoft Docs >図形と基本描画の概要 - WPF .NET Framework | Microsoft Docs >C# - 【WPF】Dictonaryの値をコンボボックスに表示できない、クラスを参照したい|teratail リンク、サンプルソースを見させていただきました。 ザムル側に形状を記述、非MVVM形式の記述だったので 今少し、ほしい情報がありませんでした。 動く状態で動作確認ができていない状態です。 参考までにShapesクラスを使用するサンプルを動かす時の プロジェクトは.Net Frameworkで作成すればよろしいでしょうか? .net coreで環境を作って確認しようとしたのですが うまく行きませんでした。
TN8001

2021/07/15 05:41

> .net coreで環境を作って確認しようとしたのですが > うまく行きませんでした。 Microsoft.Xaml.Behaviors.WpfとReactivePropertyをNuGetで入れれば、CoreでもFWでもどちらでもいいはずです。 Q&Aサイトで「うまくいかない」というのは禁句に近いです。 コンパイルできないとか(エラー文があればそれも)、メニューを押してもなんの反応がないとかそういう具体的なことを書いてください。
BluOxy

2021/07/15 08:09 編集

(横から失礼します) > そういったちょっと気合を入れた回答は、(質問者がドン引きするのか)なぜか反応が芳しくない 第三者としては、気合の入った回答は興味深かったり参考になったりすることがあるので助かります。 ※余談ですが、ちょうど最近 SVG ファイルを解析して WPF アプリ上に図形を表示する実装を作っていたので、TN8001 さんが書かれたコードを見て個人的にタイムリーな気分(?)になりました
TN8001

2021/07/15 08:14

ありがとございます^^ 質問者以外にも役に立つあるいは面白い回答を意識してはいます。 乗ってきちゃうと書きすぎてしまうので、やりすぎない(回答内容的にも文字数的にも)ようにするのが結構大変だったりします^^; まあ「ブログにでも書けよ」って話なんですがw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問