“古い祭壇で新しい料理を作る”-SOD MVVMフレームワークがWinformsに新しい春をもたらす

“古い祭壇で新しい料理を作る”-SOD MVVMフレームワークがWinformsに新しい春をもたらす

WinForms上のMVVM技術の必要性は、MVVMフレームワークを実現することは難しくないことを発見し、キーはモデル(Model)とビュー(View)の双方向バインディング、すなわちモデルの変更はビュー内容の変更を引き起こし、ビューの変更はモデルの変更を引き起こすことができる。

最后更新 2021/11/23 21:13
用户1177503
预计阅读 10 分钟
分类
Winform
专题
Winformコントロール·ライブラリ
标签
.NET Winform MVVM Winformオープンソースプロジェクト オープンソースソース

1. ホットなMVVMフレームワーク。

最近数年で最もホットな技術の一つはフロントエンド技術であり、各種フロントエンドフレームワーク、フロントエンド標準とフロントエンド設計スタイルが無限に出現しており、多くのフロントエンドフレームワークの中でMVC、MVVM機能を持つフレームワークはまばゆい新星になっています。例えばGitHubの注目度が非常に高いVue.js、中国人の作品であるため、その設計スタイルとドキュメントの友好度は中国人にとってさらに優れているので、私もそれを会社に推薦して採用します。私がお勧めする理由の一つは、非常に優れたMVVM機能であり、DOMの詳細ではなくデータ指向であり、jQueryなどよりもコードを節約し、バックエンドプログラマーの食欲に沿っており、UIデザイナーとプログラマーの分業にも役立ちます。

MVVM機能を実装するVue.jsの回路図は次のとおりです。

前述のVue.jsフレームワークの利点はよく知られているか?はい、これはWPFの初期のMVVM技術であり、Win Forms技術と比較して、WPFはUIデザイナーにより強力な設計能力を提供し、より美しく美しいインターフェースを作成することができます。しかし、MSの多くの技術は常に非常に早く、Win Formsが新しく発売されたとき、WPFはまだデスクトップ開発の主な分野を占めており、モバイル開発の時代が来ていない、Webベースのフロントエンド技術が大幅に開発されたので、WPFをカバーしていますが、WPFによって導入されたMVVMアイデアはWebフロントエンドで繁栄し、今ではMVVMベースのフロントエンドフレームワークの様々な種類が出現しています。

2. Win FormsでのMVVM要件

Webフロントエンド技術の積極的な開発、HTML 5モバイルフロントエンド開発技術に基づくクロスプラットフォームの様々な、徐々に成熟し、様々なアプリケーションは徐々に伝統的なC/SからB/S、APPモードに変換され、WPFの注目などのC/Sモードに基づくフロントエンド技術は徐々に減少しているので、MVVM上のWPFは広く使用されていない、多くのレガシーまたは新しいC/SシステムはまだWin Forms技術を使用しています。しかし、Win Formsは良いMVVMフレームワーク、Win Forms UI効果と全体的な開発品質を持っておらず、開発効率は効果的に改善されておらず、WPF開発のこの異なる開発スタイルの技術的難しさに過剰になるので、Win FormsにMVVMフレームワークがある場合は、間違いなくバックエンド. NETプログラマの大多数の恩恵です。

著者は、Webとデスクトップのためのフロントエンド開発者、アーキテクトであり、バックエンド開発技術は広く関与しており、開発者が自分自身を“コード農家”と自嘲する心理を深く理解しており、一生懸命働き、ガールフレンドと家族と過ごす時間がないので、私は開発効率を向上させ、開発品質を向上させる方法をまとめてきました。ほぼ10 年後、開発フレームワーク-SODフレームワークのセットを開発し、改善しました。最近の研究では、Webフロントエンド開発技術を改善し、Vue.jsフレームワークのMVVMアイデアは、Win Forms上のMVVM技術の必要性を再び感じさせ、MVVMフレームワークを実装することは難しくないことがわかりました。キーは、モデル(Model)とビュー(View)の双方向バインディングです。つまり、モデルの変更はビューの内容の変更を引き起こし、ビューの変更もモデルの変更を引き起こすことができます。

3. SOD Win Forms MVVMの実装原理

この変更を実現するためには,バインド先に対してプロパティ変更通知機能を持たなければならず,バインド先が変更された場合には,バインド先に対応する処理を行うよう通知する. . NETでは、この通知機能を実装するインターフェイスは次のとおりです。

INotifyPropertyChanged

System.dllで定義され、. NET 2.0でサポートされている。インターフェイスの具体的な定義は次のとおりです。

namespace System.ComponentModel
{
    // 摘要:
    //     向客户端发出某一属性值已更改的通知。
    public interface INotifyPropertyChanged
    {
        // 摘要:
        //     在更改属性值时发生。
        event PropertyChangedEventHandler PropertyChanged;
    }
}

SODフレームワークのEntityBaseベースクラスは、このインターフェイスを実装しています:

public abstract class EntityBase : INotifyPropertyChanged, ICloneable, PWMIS.Common.IEntity
{
    /// <summary>
    /// 属性改变事件
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
    /// <summary>
    /// 触发属性改变事件
    /// </summary>
    /// <param name="propertyFieldName">属性改变事件对象</param>
    protected virtual void OnPropertyChanged(string propertyFieldName)
    {
        if (this.PropertyChanged != null)
        {
            string currPropName = EntityFieldsCache.Item(this.GetType()).GetPropertyName(propertyFieldName);
            this.PropertyChanged(this, new PropertyChangedEventArgs(currPropName));
        }
    }
    // 其他代码略… …
}

したがって、SODフレームワークのエンティティークラスはMVVM 上のモデルとしてビューに直接使用できるため、Win Forms形式のView要素がバインド操作を実装する方法を解決するだけで、Win FormsアプリケーションはMVVM機能を実装できます。Win Formsでは、コントロールは基本的にバインディング機能を実装しています。これはコントロールのDataBindingsであり、次の例のようにバインディングを追加することができます。

this.textbox1.DataBindings.Add("Text", userEntity, "Name");

テキストフレームへの入力が変更されると、エンティティオブジェクトuserEntity.Nameプロパティの値も変更されます。userEntityがSODエンティティークラスの場合、userEntity.Nameが変更され、テキストボックスのTextプロパティも同期して変更されます。

SODフレームワークのデータコントロールWinForms、WebFormsは、IData Controlインターフェイスを実装し、LinkObject、LinkPropertyのいくつかの重要なプロパティを定義しています。

/// <summary>
/// 数据映射控件接口
/// </summary>
public interface IDataControl
{

    /// <summary>
    /// 与数据库数据项相关联的数据
    /// </summary>
    string LinkProperty
    {
        get;
        set;
    }

    /// <summary>
    /// 与数据关联的表名
    /// </summary>
    string LinkObject
    {
        get;
        set;
    }
    // 其他接口方法内容略… …

LinkObjectを使用してバインドするエンティティークラスオブジェクトを指定し、LinkPropertyを使用してバインドするオブジェクトのプロパティを指定できます。したがって、Win FormsコントロールとSODエンティティークラスの双方向バインドは、次のコードで実装できます。

public void BindDataControls(Control.ControlCollection controls)
{
    var dataControls = MyWinForm.GetIBControls(controls);
    foreach (IDataControl control in dataControls)
    {
        //control.LinkObject 这里都是 "DataContext"
        object dataSource = GetInstanceByMemberName(control.LinkObject);
        if (control is TextBox)
        {
            ((TextBox)control).DataBindings.Add("Text", dataSource, control.LinkProperty);
        }
        if (control is Label)
        {
            ((Label)control).DataBindings.Add("Text", dataSource, control.LinkProperty);
        }
        if (control is ListBox)
        {
            ((ListBox)control).DataBindings.Add("SelectedValue", dataSource, control.LinkProperty, false, DataSourceUpdateMode.OnPropertyChanged);
        }
    }
}

また、いくつかのコマンドをビューにバインドする必要があるかもしれませんが、これも簡単です:

private Dictionary<object, CommandMethod> dictCommand;
public delegate void CommandMethod();

public void BindCommandControls(Control control,CommandMethod command)
{
    if (control is Button)
    {
        dictCommand.Add(control, command);
        ((Button)control).Click += (sender, e) => {
            dictCommand[sender]();
        };
    }
}

このプロセスの後、フォームロードイベントに以下の行を記述するだけです。

SubmitedUsersViewModel DataContext{get;set;}

private void Form1_Load(object sender, EventArgs e)
{
    base.BindDataControls(this.Controls);
    base.BindCommandControls(this.button1, DataContext.SubmitCurrentUsers);
    base.BindCommandControls(this.button2, DataContext.UpdateUser);
    base.BindCommandControls(this.button3, DataContext.RemoveUser);
}

上記のコードでは、まずビューモデルオブジェクトDataContextを定義し、メソッドBindDataControls内でビューコントロールにバインドされたオブジェクトとして、CurrentUserプロパティのNameプロパティはテキストボックスコントロールにバインドされているので、CurrentUser.Nameは複合プロパティとしてバインドされており、ラベルコントロールとリストボックスコントロールについても同様のプロセスである。

したがって、ビュー上で簡単なデータプロパティ設定を行い、コードバックバインディングコードを少量書くだけで、双方向バインディング機能を備えたプログラムが良いでしょう。

4. MVVMサンプルソリューション

4.1ソリューション概要

SODフレームワークがMVVMをサポートすることを示すために、MVVMの3つの主要部分に対応する3つのプロジェクトアセンブリに分かれたシンプルなソリューションを構築しました。

  1. WinFormMvvm WinFormサンプルプログラムメインプログラム、ビュークラスが存在するアセンブリ
  2. WinFormMvvm.Model-モデル·クラス·アセンブリ
  3. WinFormMvvm.ViewModel-ビュー·モデル·アセンブリ

完成したソリューションは以下のとおりです。

**注意:このソリューションはSOD Ver 5.5.5.10 19で行われました。これはnuget 上のSODの現在のバージョンであり、最新のSODフレームワークはWin FormMvvmプロジェクトのMvvmForm.csファイルをフレームワークに組み込んでいるためです。

程序在 App.config 中指定了本次附加测试的数据库,数据库类型为 Access,默认的连接字符串可能要求 Office 2007 以上版本支持。

App.configの内容は以下の通りです。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name ="default" connectionString ="Provider=Microsoft.ACE.OLEDB.12.0;Jet OLEDB:Engine Type=6;Data Source=testdb.accdb" providerName="Access"/>
  </connectionStrings>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="PWMIS.Core" publicKeyToken="17ba13a12b9fd814" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.5.5.1019" newVersion="5.5.5.1019" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

以前のバージョンのAccessデータベースのサポートが必要な場合、またはSqlServerなどの別のデータベースに切り替える場合は、以下の手順を参照してください。

  1. 以下のリンクを開く:

http://pwmis.codeplex.com/

  1. “3、App.configファイルの接続設定を変更する”というセクションが表示されます。

  2. このセクションの下のリンク“2.2.3拡張データアクセスクラスの構成”をクリックします。

4.2 MVVM用のWinFormビューの作成

これはシンプルなWin Formフォームで、3つのSOD“データコントロール”があります。ユーザー IDを表示するラベルコントロール、ユーザー名を表示するテキストボックスコントロール、ユーザーのリストがすでに存在することを示すリストボックスコントロール、リストにデータを追加、変更、削除するための3つのボタンです。

データコントロールについては、このフォームデザイナインターフェイスで“ツールボックス”を開き、“一般”タブでコンテキストメニュー“オプション”を選択し、packages\PDF.NET.SOD.Win Form. Extensions.5.5.5.1020\libディレクトリを参照し、“Pwmis. Windows.dll”を選択してSODのデータコントロールを表示し、フォームにドラッグします。

** 3つのボタンコントロールに直接クリックイベントを設定するのではなく、コマンドバインディングの形で設定します。例えば、追加ボタンに対応して、次のようにバインドコマンドを実行します(ビューモデルのメソッド):**

base.BindCommandControls(this.button1, DataContext.SubmitCurrentUsers);

これにより、ユーザーのボタンコントロールを追加するクリックイベントがDataContextのSubmitCurrentUsersメソッドにバインドされます。

データ制御のバインディングには、次の1行のコードが必要です。

base.BindDataControls(this.Controls);

前述したように、このメソッドはメソッドの最初の引数内のすべてのデータコントロールを反復し、LinkObjectプロパティとLinkPropertyプロパティを見つけ、データコントロールとビューモデルオブジェクト(この場合はDataContextオブジェクトのCurrentUserオブジェクトのプロパティ)のバインディングを実装します。

プロパティブラウザでデータコントロールのLinkPropertyプロパティの横にある[]ボタンをクリックすると、次の[データコントロールプロパティセレクタ]フォームがポップアップします。

ここでバインドしたいオブジェクトは現在のフォームのDataContextオブジェクトであるため、メインアセンブリを参照して選択し、プロパティ名列にオブジェクトのすべてのプロパティとサブプロパティが表示されます。DataContextオブジェクトがリストに表示されない場合は、FormフォームがDataContextオブジェクトを宣言しているかどうかをチェックし、最初にアセンブリをコンパイルする必要があります。最後に、[OK]をクリックすると、データコントロールにバインドする情報が設定されます。

4.3 MVVMモデルの作成

私たちのモデルはシンプルで、新しいユーザーの作成、既存のユーザーの読み込み、ユーザーの追加、変更、削除を行い、これらの操作はすべてデータベースに対して行われます。この例にはロジックがあまりないので、コードを見てみましょう:

public class UserModel
{
    private static int index = 0;
    private LocalDbContext context;
    public UserModel()
    {
        context = new LocalDbContext();
    }

    public List<UserEntity> GetAllUsers()
    {
        var list= OQL.From<UserEntity>().ToList(context.CurrentDataBase);
        int max = list.Max(p => p.ID);
        index = ++max;
        return list;
    }
    public void UpdateUser(UserEntity user)
    {
        int count= context.Update<UserEntity>(user);
    }

    public void AddUsers(IList<UserEntity> users)
    {
        int count = context.AddList(users);
    }

    public void SubmitUser(UserEntity user)
    {
        int count = context.Add(user);
    }

    public void RemoveUser(UserEntity user)
    {
        int count = context.Remove(user);
    }

    public UserEntity CreateNewUser(string userName="NoName")
    {
        return new UserEntity()
        {
              ID= ++index,
              Name =userName
        };
    }
}

User ModelクラスはUser Entityクラスを使用します。これも単純で、ID属性とName属性が1つしかありません。

public class UserEntity:EntityBase
{
    public UserEntity()
    {
        TableName = "Tb_User";
        PrimaryKeys.Add("UserID");
    }
    public int ID {
        get { return getProperty<int>("UserID"); }
        set { setProperty("UserID", value); }
    }

    public string Name
    {
        get { return getProperty<string>("UserName"); }
        set { setProperty("UserName", value); }
    }

}

このユーザーエンティティークラスはシンプルですが、SODエンティティークラスはすべて、前述のようにプロパティ変更通知インターフェイスを実装しているため、モデルバインド要素としてビューに直接提供できます。

次に、このユーザエンティティクラスを操作するデータコンテキストがあります。ユーザモデルクラスはその使用方法を示しますが、定義は簡単です。

class LocalDbContext : DbContext
{
    public LocalDbContext()
        : base("default")
    {
        //local 是连接字符串名字
    }

    protected override bool CheckAllTableExists()
    {
        //创建用户表
        CheckTableExists<UserEntity>();
        return true;
    }
}

これで、単純なMVVMモデルクラスの完全な定義は完了です。

4.4 MVVMのビューモデルの作成。

ビューモデルはビューの抽象化であり、主要なビュー処理ロジックをカプセル化しているが、MVPのPresenterとは異なり、ビューモデルは抽象リストコントロールのような詳細なビュー要素の抽象化を含まず、ビューが使用する可能性のあるデータをカプセル化し、バックエンドMVVMへのモデルオブジェクト呼び出しを含むことができる。

この例では、ユーザビューモデルの機能も非常に単純です。ビューに必要なユーザのリストと、ビューに応答するユーザの追加、変更、削除のコマンドを提供することです。

public class SubmitedUsersViewModel
{

    private UserModel model = new UserModel();
    public BindingList<UserEntity> Users { get; private set; }
    public UserEntity CurrentUser { get; private set; }


    UserEntity _selectUser;
    /// <summary>
    /// 当前选择的用户,如果设置,则会设置当前用户
    /// </summary>
    public UserEntity SelectedUser {
        get { return _selectUser; }
        set {
            _selectUser = value;
            this.CurrentUser.ID = value.ID;
            this.CurrentUser.Name = value.Name;
        }

    }

    int _selectedUserID;
    public int SelectedUserID
    {
        get { return _selectedUserID; }
        set {
            _selectedUserID = value;
            var obj = this.Users.FirstOrDefault(p=>p.ID==value);
            if (obj != null)
            {
                this.CurrentUser.ID = obj.ID;
                this.CurrentUser.Name = obj.Name;
                _selectUser = this.CurrentUser;
            }

        }
    }

    public SubmitedUsersViewModel()
    {
        var data = model.GetAllUsers();
        Users = new BindingList<UserEntity>(data);
        CurrentUser = new UserEntity();

    }

    public void UpdateUser()
    {
        var obj = this.Users.FirstOrDefault(p => p.ID == this.CurrentUser.ID);
        if (obj != null)
        {
            obj.Name = this.CurrentUser.Name;
            //更新后必须调用 ResetBindings 方法,否则控件上的数据会丢失一行
            this.Users.ResetBindings();

            model.UpdateUser(obj);
        }

    }
    public void UpdateUser(int id,string name)
    {
        var obj = this.Users.FirstOrDefault(p => p.ID == id);
        if (obj != null)
        {
            obj.Name = name;
            //更新后必须调用 ResetBindings 方法,否则控件上的数据会丢失一行
            this.Users.ResetBindings();

            model.UpdateUser(obj);
        }
    }

    public void SubmitUsers(UserEntity user)
    {
        //UserEntity newUser = new UserEntity();
        //newUser.ID = user.ID;
        //newUser.Name = user.Name;
        //Users.Add(newUser);
        if (!Users.Contains(user))
        {
            Users.Add(user);
            model.SubmitUser(user);
        }
    }
    public void SubmitCurrentUsers()
    {
        UserEntity newUser = model.CreateNewUser(CurrentUser.Name);
        SubmitUsers(newUser);
        CurrentUser.ID = newUser.ID;
    }

    public void RemoveUser()
    {
        if (SelectedUser == null)
        {

            return;
        }
        var obj = this.Users.FirstOrDefault(p => p.ID == SelectedUser.ID);
        if (obj != null)
        {
            this.Users.Remove(obj);
            //更新后必须调用 ResetBindings 方法,否则控件上的数据会丢失一行
            this.Users.ResetBindings();

            model.RemoveUser(obj);
        }
    }
}

4.5 NuGetパッケージリファレンスの追加

ソリューション全体では、すべてのPDF.NET Coreパッケージを追加する必要がありますが、Win Formsメインプログラムでは、SOD Win Form拡張機能とSOD Access拡張機能の2つの関連パッケージを追加する必要があります。ソリューションインストールの完全なパッケージ図は次のとおりです。

4.6ソリューションの実行。

上記のプロセスの後、ビュー要素を追加し、ビュー要素のデータバインディングを設定し、モデルとビューモデルオブジェクトを作成し、単純なMVVMサンプルプログラムを作成します。

5. MVVMモードまとめ

この例を実行することで、MVVMのいくつかの機能を経験したと思いますが、適切に表現するのは難しいかもしれませんが、WPFのベテラン専門家と話したところ、MVVMのいくつかのコア機能(セールスポイント)をまとめました。

  1. ビュー論理(ビューモデル)とビュー(ビュー要素、スタイル)の結合解除;

  2. ビューとビューモデルまたはモデルの双方向データバインディングは、ビュー駆動型データではなく、データ駆動型ビューを指向しています。

  3. ビューとビューモデルとのは、インタフェースを全てコード化し、また可能性を提供する。

6. SOD Win Forms MVVMのサポート

SODフレームワークのバージョン5.6.0.1 1 1 1でリリースされたこの“シングルデー”リリース以降、Win Forms MVVMを直接サポートすることができます。以前のバージョンの場合は、このサンプルプログラムのようにもう少し作業する必要がありますが、既存のSODサポートソリューションには影響しません。

本示例方案将会放到框架的开源网站 http://pwmis.codeplex.com 上提供直接的下载,并且源码已经全部提交,可以通过下面地址查看详细的代码说明:

http://pwmis.codeplex.com/SourceControl/latest#SOD/Example/WinFormMvvm/WinFormMvvm/Readme.txt

詳細については、コミュニティQQグループディスカッションに参加したり、このフレームワークに寄付したりするには、フレームワークの公式サイトをご覧ください。

http://www.pwmis.com/sqlmap

SODフレームワークをお選びいただきありがとうございます。あなたの開発に大きなメリットをもたらすと思います。

SODの開発チーム

ドクター·ディープブルー

2016.11.13

------------PS---------------

SOD開発チームの@広州-Yingu学生に感謝します。彼はSODフレームワークのnugetパッケージをタイムリーに最新バージョンに更新し、前述のnugetパッケージの問題はありません。

SODライブラリリポジトリのアドレスとスクリーンショット情報を添付します:

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2024/02/29

Winformでもデータを表示できます。

winform開発の過程では、しばしばデータ表示機能を行う必要がありますが、以前はグリッドコントロールを使用していましたが、今日は例を通じて、Winform Blazorハイブリッドでant Design Blazorテーブルコンポーネントを使用してデータ表示を行う方法を紹介します。

继续阅读
同分类 / 同标签 2024/02/29

Winformのインターフェースも良く見えますか?

先日、winformでBlazorハイブリッドを使用することを紹介しましたが、Blazor UIを使用するとwinformプログラムがより良く見えるようになると述べました。次に、winform Blazorハイブリッドで描画する例を示したいと思います。

继续阅读