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

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

ただいまの
回答率

90.47%

  • C#

    9241questions

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

  • WPF

    843questions

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

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

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 5,196

k-hi

score 15

こんにちは。
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

namespace Cherry.Models{
 public class People{
  public string PersonName { get; set; }
 }
}

MainWindow.xaml

<Window><Grid>
<TextBox x:Name="personname"/>
</Grid>
</Window>

MainWindow.xaml.cs

namespace Cherry {
 public class MainWindow : Window {

  public MainWindow(){
    InitializeComponent();
  }

  private void MainWindow_Loaded(object sender, RoutedEventArgs e) {
   Models.People person = new Models.People();
   person.PersonName = "Cyndi Lauper";
   personnametextbox.Text = "Cyndi Lauper";
  }

  private void RoomAButton_Click(object sender, RoutedEventArgs e) {
   var roomAWindow = new RoomAWindow(this);
   roomAWindow.Show();
  }

  private void RoomBButton_Click(object sender, RoutedEventArgs e) {
   var roomAWindow = new RoomAWindow();
   roomBWindow.Show();
  }
 }
}

RoomAWindow.xaml.cs

namespace Cherry {
 public class RoomAWindow : Window {
   MainWindow mainWindow;
   public RoomAWindow(MainWindow mainwindow){
    InitializeComponent();
    mainWindow = mainwindow;
    //ここでperson.PersonName(=="Cyndi Lauper")を取り出したい。
   }
  }


RoomBWindow.xaml.cs

namespace Cherry {
 public class RoomBWindow : Window {
   public RoomBWindow(){
    InitializeComponent();
    //ここでperson.PersonName(=="Cyndi Lauper")を取り出したい。
  //PeopleクラスのPersonNameにアクセスするには、
    People person = new People();
    string wantname = person.PersonName;
    だが、これだと新規の名前(null)になる。
   }
  }
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

まず前提として

public class People{
  public string PersonName { get; set; }
}

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

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

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

int 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/12 18:21

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

    キャンセル

  • 2016/08/12 18:52 編集

    サンプル見て勉強してくださいとしか

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

    キャンセル

check解決した方法

0

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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/15 14:57

    ありがとうございます。
    WPFを使って、見栄えのよいアプリケーションは(ある程度)作れます。C#も基本はわかります。
    ただ、MVVMをちょっと触って、とても興味深く感じたので、MVVMで作ってみたい、という気持ちが強くなりました。
    触ったのは、別の方が作ったprojectを触れていただけで、自分で0から作ったのではありませんでした。
    今回、0から作れる機会を得たので、MVVMで作ってみたい、ということです。

    いろいろ参考にして、現在、部分的にMVVMになっています。
    8画面(8class)くらいのapplicationで、2画面くらいがMVVM、のこりがWPFです。
    今回質問しているのは、そのMVVMとWPFの両方で、PersonNameを共通で使いたいためです。

    WebのMVVMはだいぶ見たのですが、最小のコードのサンプルは少なく、過剰すぎて、必要な情報を抽出するのに苦戦している、そこで質問した、ということです。
    というわけで、grobalにもつ方法でないMVVMの方法を、ご教示いただければうれしいです。

    キャンセル

  • 2016/08/15 22: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の記事で大体のことはわかるものと思います。

    キャンセル

-1

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

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

public static MainWindow Instance = null;

コンストラクタで、

Instance = this;

としておけば、

RoomBWindowのメソッド内から

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/08/10 13:52 編集

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

    キャンセル

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

  • ただいまの回答率 90.47%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

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

  • C#

    9241questions

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

  • WPF

    843questions

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