Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@qyen

EntityFrameworkのデータファーストでモデルクラスをINotifyPropertyChangedに対応させる

More than 1 year has passed since last update.

EntityFrameworkサイコー

EFのデータファーストが最高なので、INotifyPropertyChangedに対応したらもっとサイコーになるよね。
的な。

INotifyPropertyChanged の実装超めんどい

なのでハイパー最高なNuGetのPropertyChanged.Fodyを使う。
INotifyPropertyChangedを自動実装してくれるPropertyChanged.fodyが超便利 - Azureはじめました

上の記事はPropertyChanged.Fodyのかなり古いバージョンなので今この通りに実装するとそんな古い形式使ってんじゃねーよばーかばーか的なエラーになるので注意。

NotifyPropertyChanged.Fodyの実装方法


public class HogeModel{
    public string Name{get;set;}
    public int AnyNumber{get;set;}
}

これを

using System.ComponentModel;

public class HogeModel{
    public event PropertyChangedEventHandler PropertyChanged;

    public string Name{get;set;}
    public int AnyNumber{get;set;}
}

こうする。

後はプロジェクトにFodyWeavers.xmlというファイルを追加して

FodyWeavers.xml
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
  <PropertyChanged/>
</Weavers>

こうするだけ。超便利。

INotifyPr(略) をedmx で出力しているクラスにどう実装するか

edmxを構成するモデル出力用のT4テンプレートを直接編集すればOK

スクリーンショット (80).png

PropertyChanged.Fodyで追加する記述は

  1. usingにSystem.ComponentModelを追加
  2. class定義にINotifyPropertyChangedを追加
  3. メンバに PropertyChangedEventHandlerを追加

なのでそれぞれ追記する。

1. usingにSystem.ComponentModelを追加

usingを出力しているのは codeStringGenerator.UsingDirectives()なのでそこに追記

public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
    return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
        ? string.Format(
            CultureInfo.InvariantCulture,
            "{0}using System;{1}" +
            "{2}",
            inHeader ? Environment.NewLine : "",
            (includeCollections ? (Environment.NewLine + "using System.Collections.Generic;") : "")
                +Environment.NewLine +"using System.ComponentModel;", //これ
            inHeader ? "" : Environment.NewLine)
        : "";
}

2. class定義にINotifyPropertyChangedを追加

class定義を出力してるのはcodeStringGenerator.EntityClassOpening()

public string EntityClassOpening(EntityType entity)
{
    return string.Format(
        CultureInfo.InvariantCulture,
        "{0} {1}partial class {2}{3}",
        Accessibility.ForType(entity),
        _code.SpaceAfter(_code.AbstractOption(entity)),
        _code.Escape(entity),
        ":INotifyPropertyChanged"); //これ
        //_code.StringBefore(" : ", _typeMapper.GetTypeName(entity.BaseType)));
}

(entity.BaseType使わないので横着した。使う場合は適宜修正を。)

3. メンバに PropertyChangedEventHandlerを追加

テンプレートの先頭の方にあるEntityClassOpening(entity)の後に直接記述

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
    #pragma warning disable 0067 
    public event PropertyChangedEventHandler PropertyChanged; //これ
    #pragma warning restore 0067 

ただPropertyChangedEventHandlerを追加しただけだと CS0067(未使用のメンバ)が表示されて大変鬱陶しいのでpragma warning disable - restoreを使って警告表示を抑制してみた。

[C#]コンパイル時の警告を抑制する | anopara

あとはファイルを保存してコンパイルすればOK。
こんな感じに出力される。

//------------------------------------------------------------------------------
// <auto-generated>
//     このコードはテンプレートから生成されました。
//
//     このファイルを手動で変更すると、アプリケーションで予期しない動作が発生する可能性があります。
//     このファイルに対する手動の変更は、コードが再生成されると上書きされます。
// </auto-generated>
//------------------------------------------------------------------------------

namespace models
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;

    public partial class 銀行マスタ:INotifyPropertyChanged
    {
            public event PropertyChangedEventHandler PropertyChanged;
            [Key]
            public string 銀行コード { get; set; }
            public string 銀行名 { get; set; }
            public string 銀行カナ { get; set; }
    }
}

いいね!

使いみちとか

INotifyPropertyChanged吐けばWinFormsのDataBindingとかWPFのBindingとかが勝手にリセットしてくれるので、ViewModel的に使ったりマジなんでもありでサイコー。

6
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
qyen

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?