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

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

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

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

WPF

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

Q&A

解決済

4回答

13906閲覧

C#, WPF, MVVMのClass設計の具体例を教えてください。

k-hi

総合スコア21

C#

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

WPF

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

0グッド

2クリップ

投稿2016/08/10 02:58

こんにちは。
Class設計の具体例を教えてください。
MainWindowからRoomAWindowとRoomBWindowを開いています。
MainWindowで設定したModelsのPeopleクラスのNameをRoomAWindowとRoomBWindowで共通に使いたいです。
ひとつの方法は、
public string PersonName { get; set; }

public static string PersonName { get; set; }
とすることです。
これって一般的なのでしょうか?

現在のファイル構造と内容です。
よろしくご示唆ください。

└─Cherry
├─Cherry
│ ├─Models
│ │ ├─People.cs
│ │ └─Cherry.cs
│ ├─View
│ │ ├─MainWindow.xaml
│ │ ├─MainWindow.xaml.cs
│ │ ├─RoomAWindow.xaml
│ │ ├─RoomAWindow.xaml.cs
│ │ ├─RoomBWindow.xaml
│ │ └─RoomBWindow.xaml.cs

People.cs

C#

1namespace Cherry.Models{ 2 public class People{ 3 public string PersonName { get; set; } 4 } 5}

MainWindow.xaml

xaml

1<Window><Grid> 2<TextBox x:Name="personname"/> 3</Grid> 4</Window>

MainWindow.xaml.cs

C#

1namespace Cherry { 2 public class MainWindow : Window { 3 4 public MainWindow(){ 5 InitializeComponent(); 6 } 7 8 private void MainWindow_Loaded(object sender, RoutedEventArgs e) { 9 Models.People person = new Models.People(); 10 person.PersonName = "Cyndi Lauper"; 11 personnametextbox.Text = "Cyndi Lauper"; 12 } 13 14 private void RoomAButton_Click(object sender, RoutedEventArgs e) { 15 var roomAWindow = new RoomAWindow(this); 16 roomAWindow.Show(); 17 } 18 19 private void RoomBButton_Click(object sender, RoutedEventArgs e) { 20 var roomAWindow = new RoomAWindow(); 21 roomBWindow.Show(); 22 } 23 } 24}

RoomAWindow.xaml.cs

C#

1namespace Cherry { 2 public class RoomAWindow : Window { 3 MainWindow mainWindow; 4 public RoomAWindow(MainWindow mainwindow){ 5 InitializeComponent(); 6 mainWindow = mainwindow; 7 //ここでperson.PersonName(=="Cyndi Lauper")を取り出したい。 8 } 9 }

RoomBWindow.xaml.cs

C#

1namespace Cherry { 2 public class RoomBWindow : Window { 3 public RoomBWindow(){ 4 InitializeComponent(); 5 //ここでperson.PersonName(=="Cyndi Lauper")を取り出したい。 6 //PeopleクラスのPersonNameにアクセスするには、 7 People person = new People(); 8 string wantname = person.PersonName; 9 だが、これだと新規の名前(null)になる。 10 } 11 } 12}

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

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

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

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

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

guest

回答4

0

まず前提として

C#

1public class People{ 2 public string PersonName { get; set; } 3}

と言うのはあくまで型の定義です。
実体は生成しなければ存在しませんし、複数存在しえます。

var p1 = new People(); var p2 = new People(); // p1とは別物

例えばうんと単純にしてint型:

C#

1int x = 0;

とどこかに書いて、別の場所でも使いたかったら、
これ(の参照)を別の場所に渡さないといけないのと一緒です。

(あとPeopleクラスじゃなくてPersonクラスだと思いますが置いておきます。)


本題

ひとつの方法は、

public string PersonName { get; set; }

public static string PersonName { get; set; }
とすることです。
これって一般的なのでしょうか?

一般的云々というか場合によっては誤りです。
PersonNameがひとつしか存在しないと決めて今後一切それが覆らないなら
まあアリかなレベルです。

roomAWindowroomBWindowで両方共、
mainWindowで作ったPeopleクラスのインスタンスを参照したかったら、
当然、mainWindowからroomAWindowroomBWindow
作ったインスタンスを渡さなければなりません。

修正少なく済ませるなら、
MainWindowクラスにフィールドとして持たせて、
roomAWindow及びroomBWindowの生成時にコンストラクタの引数で渡します。


ですが、「MVVMで」という指定が付くなら話が違います。
違いますが、VMがそもそも無いので
なんか適当に文言入れただけでしょうかね?

投稿2016/08/10 14:41

編集2016/08/10 14:47
ozwk

総合スコア13512

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

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

k-hi

2016/08/12 09:21

ありがとうございます。 MVVMで、という指定で、方法をご教示いただければ幸いです。 VMがないのではなく、現状だと空なのです。
ozwk

2016/08/12 10:01 編集

サンプル見て勉強してくださいとしか VMないコード貼って MVVMやりたいと言われても、 ふんわりとしたことしか言えなくて困るので、 MVVMについてもう少し調べて、 少しはMVVMに寄せたコードを書いてみて、 その上で再度質問してみてはどうでしょう?
guest

0

自己解決

時間切れでMVVMを使うのはやめました。

投稿2016/09/26 14:56

k-hi

総合スコア21

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

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

0

まず、確認したいのですが、WPFを使ってアプリケーションを作成しようとしているのは、見栄えのいいアプリケーションを作りたいだけでしょうか?もしそうならModelをグローバルに持ってどこからでもアクセスできようにしてでも全然構いません。MVVMにこだわる必要はないと思います。

次に、WPFを使いMVVMで作りたいということ(+見栄えのいいアプリケーションでももちろんOK)であれば、ViewModel抜きでば考えられません。この場合、まずViewModelクラス(DependencyObjectの派生クラス)を作ります。クラス名は何でもいいです。次にViewModelクラスにModelを持たせるようにします。プロパティでもフィールドでもいいです。その上で、ViewModelクラスのインスタンスをMainWindowのコンストラクターでDataContextプロパティに設定し、さらに他のWindowを作成する際にこのViewModelのインスタンスを各WindowのDataContextに設定します。これですべてのWindowからModelにアクセスできるようになります。(ここまでなんとなくわかりますよね?…すみません、C#とかはわかるつもりで書いてますので)
でも、これだけだとMVVMになってません。MもVもVMも存在しますがつながってない…で、ここからが依存関係プロパティの出番です。たとえば、Modelが変更されたら、各Windowが変更されたことの通知をもらって表示するとか必要になります。これをイベントで処理することも可能ですが、WPFだとViewModelとWindow側に依存関係プロパティを持たせて、それをBindingしてつなぎます。こうした状態でModelを変更したら、同時にViewModelの依存関係プロパティを変更することでWindowにも変更が通知されることになります。非常におおざっぱですが、これで非常に簡単なMVVMになります。

と、ざっと書きましたがたぶん、これでわかるとは思いません。実のところこWPFを始める頃にはだれでも悩むところなのです(私もさんざん悩みました)。ただ、なんとなくViewModelを書いてみて、依存関係プロパティを作ってBindingして…とやってるうちに、おぉ、これか!と悟りを開いた感じになりした(大げさですが)。ともかく、MVVMでということならまずViewModelです。そして依存関係プロパティ、Binding、とやってみてください。詳細はWebを検索すると例は沢山あると思います。がんばってください。

投稿2016/08/13 22:39

mabmab

総合スコア20

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

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

k-hi

2016/08/15 05:57

ありがとうございます。 WPFを使って、見栄えのよいアプリケーションは(ある程度)作れます。C#も基本はわかります。 ただ、MVVMをちょっと触って、とても興味深く感じたので、MVVMで作ってみたい、という気持ちが強くなりました。 触ったのは、別の方が作ったprojectを触れていただけで、自分で0から作ったのではありませんでした。 今回、0から作れる機会を得たので、MVVMで作ってみたい、ということです。 いろいろ参考にして、現在、部分的にMVVMになっています。 8画面(8class)くらいのapplicationで、2画面くらいがMVVM、のこりがWPFです。 今回質問しているのは、そのMVVMとWPFの両方で、PersonNameを共通で使いたいためです。 WebのMVVMはだいぶ見たのですが、最小のコードのサンプルは少なく、過剰すぎて、必要な情報を抽出するのに苦戦している、そこで質問した、ということです。 というわけで、grobalにもつ方法でないMVVMの方法を、ご教示いただければうれしいです。
mabmab

2016/08/15 13:34

 「MVVMをちょっと触って」とか「2画面くらいがMVVM、のこりがWPFです」という言葉から、どうもMVVM(MVVMパターン)を勘違いしているか、全く違うモノのことのような気がします。 『「コマンド」と「MVVMパターン」を理解する』(@IT) http://www.atmarkit.co.jp/ait/articles/1011/09/news102_3.html  上記のMVVMパターンと違う意味の「MVVM」とういうことであれば、残念ですが、私はわかりません。逆にMVVMパターンのことであれば、@ITの記事で大体のことはわかるものと思います。
guest

0

RoomBWindow では、新たにnew しているので、新規インスタンスとなり nullは当然です。

MainWindow のインスタンスにアクセスするためには、
public フィールドにしておき、

public static MainWindow Instance = null;

コンストラクタで、

Instance = this;

としておけば、

RoomBWindowのメソッド内から

MainWindow.Instance.PersonName でアクセスできますね。

投稿2016/08/10 04:45

mugicya

総合スコア1046

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

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

k-hi

2016/08/10 05:00 編集

ありがとうございます。 すみません。 これはRoomBWindowで処理する、ということですか? RoomBWindowでMainWindowを経由しないでPersonClassのPersonNameにはアクセスできないのでしょうか? MainWindowにはPersonNameはないのです。ご確認いただければ幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問