Giter Site home page Giter Site logo

mvvmfx / mvvmfx Goto Github PK

View Code? Open in Web Editor NEW
64.0 11.0 22.0 20.48 MB

MVVM for Wisej and Windows Forms - Caliburn.Micro and Bound controls libraries

License: MIT License

PowerShell 1.10% C# 98.20% XSLT 0.70% Batchfile 0.01%
mvvm mvvm-framework windows-forms wisej caliburn-micro caliburn winforms

mvvmfx's Introduction

MVVM for Wisej and Windows Forms

NuGet

The MVVM FX project targets Wisej and WinForms.

The project focus on providing a development framework based on these libraries:

  • General purpose data bindind and command binding library
  • Bound controls and components
  • Caliburn.Micro MVVM framework ported to Wisej and WinForms
  • Common logger for the framework

The project's main goal is the MVVM framework. Caliburn.Micro is one of the best MVVM frameworks around (some would say it is the best). Based on a partial port from Dan Durland, the missing features were added, bit by bit.

In order to do proper MVVM, one must use controls that support data binding. Some of the standard Wisej/WinForms controls don't comply with this requirement, namely TreeView. The bound controls library fills this gap.

Due to Wisej/WinForms binding shortcomings, a general purpose binding library is instrumental for the Caliburn.Micro port. The MvvmFx.Bindings library is based on Truss and includes some features that aren't needed for the Caliburn.Micro port. The same source code was used to build MvvmFx.DataBinding, a smaller version of the library, that is stripped off of all method binding parts, like Action or Command binding. Note "Caliburn.Micro does not need an implementation of ICommand because it has Actions which are superior to commands in every way", as Rob Eisenberg puts it.

Project Status

Release 3.0.1 (11 Apr 2018)

Maintenance release:

  1. Promote .NET 4.6 projects to .NET 4.6.1
  2. Fetch Wisej dependency from NuGet

N.B. - Run Wisej samples from NuGet - you don't need to install Wisej.

Release 3.0.0 (18 Feb 2018)

NuGet packages:

  • MvvmFx-Bindings-WinForms
  • MvvmFx-Bindings-Wisej
  • MvvmFx-BoundControls-WinForms
  • MvvmFx-BoundControls-Wisej
  • MvvmFx-CaliburnMicro-Csla-WinForms
  • MvvmFx-CaliburnMicro-Csla-Wisej
  • MvvmFx-CaliburnMicro-WinForms
  • MvvmFx-CaliburnMicro-Wisej
  • MvvmFx-Log4netLogger
  • MvvmFx-Logging
  • MvvmFx-NLogLogger

Explore and run InterwayDocs

  • MvvmFx Wisej/WinForms application that is an important step to test and refine concepts.
  • Latest release is 1.3.8 (21 May 2018)
  • Wisej version features:
    • change language without reloading page
    • alert when closing browser may loose unsaved information
  • Application delivered in 3 forms:
    • WebSite - Wisej web site IIS ready
    • WebStandalone - Wisej web site packed into a desktop .exe file
    • WinForms - Windows Forms desktop application

What is Wisej?

Take your WinForms project, port it to Wisej retaining all your BO/DAL code and most UI code. Now run it as a Web application. Get Wisej

License

MvvmFx is copyright MvvmFx project. Its use is governed by the MIT license.

mvvmfx's People

Contributors

tfreitasleal avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mvvmfx's Issues

Quick Start

Dear Tiago,

If I want to start a new windows forms or wisej project, how would I use your MvvmFx framework?
I tried the Documentation and Get Started folders but found .aml, .odg files which I cannot open.

All the best,
Alex

CaliburnMicro projects missing files

The following CaliburnMicro projects are missing source files.

CaliburnMicro.Csla.WebGUI.Net4
CaliburnMicro.Csla.WebGUI.Net45
CaliburnMicro.Csla.WebGUI.Net46
CaliburnMicro.Csla.WinForms.Net45
CaliburnMicro.Csla.WinForms.Net46
CaliburnMicro.DialogExtensions.WebGUI.Net4
CaliburnMicro.DialogExtensions.WebGUI.Net45
CaliburnMicro.DialogExtensions.WebGUI.Net46
CaliburnMicro.DialogExtensions.WinForms.Net4
CaliburnMicro.DialogExtensions.WinForms.Net45
CaliburnMicro.DialogExtensions.WinForms.Net46
CaliburnMicro.WebGUI.Net4
CaliburnMicro.WebGUI.Net45
CaliburnMicro.WebGUI.Net46
CaliburnMicro.WinForms.Net45
CaliburnMicro.WinForms.Net46

Async/Await

Hi. Is async/await support in MvvmFx good? I'm studying the code to see how everything works, but I don't see any async/await code anywhere.

runningProperty on DelegateCommand does not change

Hi there,

I have a non-background DelegateCommand and tried to attach a listener to the runningProperty but it does not get called, when i start the command via the execute() method. Is this intended behaviour?

I'm using MvvmFx Version 1.8.0. Here's a unit-test to verify the behaviour:

@Test
void test() {
    CountDownLatch commandExecutedLatch = new CountDownLatch(1);
    CountDownLatch listenerCalledLatch = new CountDownLatch(1);

    Command command = new DelegateCommand(() -> new Action() {
        @Override
        protected void action() throws Exception {
            commandExecutedLatch.countDown();
        }
    });

    command.runningProperty().addListener((observable, oldValue, newValue) -> {
        listenerCalledLatch.countDown();
    });

    // when
    command.execute();

    // then
    Assertions.assertDoesNotThrow(() -> {
        commandExecutedLatch.await(2, TimeUnit.SECONDS);
        listenerCalledLatch.await(2, TimeUnit.SECONDS);
    });

   Assertions.assertEquals(0, commandExecutedLatch.getCount(), "Action was not executed");
   Assertions.assertEquals(0, listenerCalledLatch.getCount(), "Listener was not invoked");
}

Cheers

Patrick

View isn't disposed, ever.

DependencyObject implementation uses objects and should use WeakReference.
Quick fix: call view.Dispose

Use lowest dependencies

Assembly redirection seems to mis-behave under Wisej.
CSLA - use 4.6.100 (instead of 4.6.603)
NLog - use 4.0.0 (instead of 4.4.12)
log4net - use 1.2.10 (instead of 2.0.8)

Add IBindableComponents

StatusBarPanel.cs, ToolBarButton.cs, ToolStripButton.cs, ToolStripDropDownButton.cs, ToolStripLabel.cs, ToolStripMenuItem.cs, ToolStripProgressBar.cs, ToolStripSeparator.cs, ToolStripSplitButton.cs, ToolStripStatusLabel.cs, ToolStripTextBox.cs.

CSLA and WinForms

Hello,

I was just looking for a "best pattern" method of binding WinForms controls like DevExpress XtraGrid to nHibernate collections. I did my own code using BindingSource, it works even with multilevel (master/detail) grids - any amount of levels.

I was aware there is better method to build applications using business level frameworks like CSLA.
It also has data binding features even for WinForms:
http://nugetmusthaves.com/Package/CSLA-WindowsForms

Then I read it is a good idea to use a ModelView pattern, especially if used together with XAML based GUI like WPF, UWP, etc. according to "Rockford Lhotka":
http://www.lhotka.net/weblog/WhyMVVM.aspx

There is an adapter for CaliburnMicro and specifically mod for WinForms:
https://github.com/MvvmFx/MvvmFx

Please suggest, is it a good idea to use following chain of components:
DevExpress WinForms XtragGrid -> MVVM->CSLA->nHibernate
?
I am reluctant to switch to WPF until MS unveils their plans to make WPF crossplatform at least on Linux.

For now DevExpress WinForms works fine on Linux + Wine and I do not have to spend time on learning WPF, look and feel of DevExpress WinForm is ok for me though my DXP license includes WPF too.

Documentation doesn't build from download

To recreate:

  1. I downloaded the ZIP of MvvmFx from the Clone or Download button.
  2. I 'Extracted all' to D:\Source\MvvmFx.
  3. In VIsual Studio 2015, I opened MvvmFx.shfbproj from 'D:\Source\MvvmFx\MvvmFx-master\Documentation\Binding'.
    • A 'One-way upgrade' was necessary.
  4. I built the solution and got two warnings and one error:
    Warning - Unable to locate any documentation sources for 'D:\Source\MvvmFx\MvvmFx-master\Documentation\bin\Release\Client\MvvmFx.Bindings.dll'
    Warning - Unable to locate any documentation sources for 'D:\Source\MvvmFx\MvvmFx-master\Documentation\bin\Release\Client\MvvmFx.Bindings.xml'
    Error: You must specify at least one documentation source in the form of an assembly or a Visual Studio solution/project file
    The Source File path in the properties were:
    ..\bin\Release\Client\MvvmFx.Bindings.dll
    ..\bin\Release\Client\MvvmFx.Bindings.xml
  5. I saved and closed the generated solution.
  6. I opened MvvmFx.All.VS2015.sln from 'D:\Source\MvvmFx\MvvmFx-master\Source'.
  7. I checked it was in Release mode and built it.
    • It restored NuGet packages...
  8. I closed the solution.
  9. I opened the documentation solution, switched to Release mode and selected Build and got the same error messages.
  10. I opened a command prompt and navigated to the shfbproj location ('D:\Source\MvvmFx\MvvmFx-master\Documentation\Binding').
  11. I attempted CD '..\bin\Release\Client' and got 'The system cannot find the path specified.' I searched and there's no Client folder under 'D:\Source\MvvmFx\MvvmFx-master'.

So I decided to link to the project to get the XML file(s).

  1. I opened 'MvvmFx.All.VS2015.sln' from 'D:\Source\MvvmFx\MvvmFx-master\Source' and did Save As... to a new solution file.
  2. I right-clicked on the solution and selected Add > Existing Project..., navigated to Documentation\Binding and selected MvvmFx.shfbproj and clicked Open.
  3. I right-clicked on Documentation Sources and selected Add Documentation Source and navigated to 'D:\Source\MvvmFx\MvvmFx-master\Source\Binding\MvvmFx.Bindings.Net45\MvvmFx.Bindings.Net45.csproj'
    and I removed the two existing Documentation Sources.
  4. I built the solution.
  5. It generated a lot of warning and an error. Amongst the warnings, I spotted:
    Warning: No documentation source XML comments files found. The help file will not contain any member comments.
  6. I opened Properties on these projects:
    • MvvmFx.Bindings.Net45
    • MvvmFx.Bindings.WinForms.Net45
    • MvvmFx.Bindings.WisejWeb.Net45
    • MvvmFx.Bindings.WPF.Net45
    • WindowsBase.WinForms.Net45
    • WindowsBase.WisejWeb.Net45
      selected the Build panel and checked the XML Documentation file box. I left the path at the default.
  7. I build the solution again and got another failure. This time I had to look in the LastBuild.log file where I found:
    Error: Could not find a part of the path D:\Source\MvvmFx\MvvmFx-master\Documentation\Src\Samples\SimpleBindings\Program.cs
  8. I created Src folder in 'D:\Source\MvvmFx\MvvmFx-master\Documentation', found the Samples folder at 'D:\Source\MvvmFx\MvvmFx-master' and moved it to 'D:\Source\MvvmFx\MvvmFx-master\Documentation\Src'.
  9. I built the solution again and that didn't work. SimpleBindings is in Samples\Bindings and should be in Samples.. I suspected the rest would be the same so I moved everything from the Samples\Binding folder into Sample.
  10. I built it again and, this time, it worked. There are loads of warnings but I did get a .chm file out of it.

How can I bind to ComboBox.SelectedItem?

I would like to bind to SelectedItem, since the ComboBox's DataSource is a list of objects, not strings. I was reworking a legacy app when I discovered this so I've created a sample project to recreate it.

I can bind to SelectedValue and see the view-model [string] Title property updated on the viewModel. When I try to bind SelectedItem to the view-model [Role] Role property the binding only works one way: when I set the view-model property in code the ComboBox is updated but when I select a new value in the ComboBox the view-model [Role] Role property is not updated.

To recreate,

  1. I created a new .Net 4.5.2 Windows Forms Application called ComboApp1. in D:\Source.
  2. Using Manage NuGet Packages..., I added MvvmFx-Bindings-WinForms (v3.0.1)
  3. I added BusinessObject from your samples.
  4. I added a Role class to be the object represented in the ComboBox.
  5. I added a Forms1ViewModel.
  6. I added a ComboBox and two TextBoxes to the form.
    1. The first TextBox has ReadOnly set to True and is to display the bound value of the Role name.
    2. The ComboBox has DropDownStyle set to DropDownList.
    3. The second TextBox exists to allow you to move the focus from the ComboBox.

The ComboBox DataSource is the [List] Roles property on the Form1ViewModel.
The ComboBox DisplayMember and ValueMember are set the "Name" property (of Role).
I use TypedBindings to bind the ComboBox SelectedItem to the Role property on the Form1ViewModel.

The Form1ViewModel Role property is set to the first object in the Roles list, to demonstrate that the binding works, source to target.

Am I doing something wrong? Should this be possible?

Classes are below and I've attached the solution:
ComboApp1.zip

Form1.cs

namespace ComboApp1
{
    using MvvmFx.Bindings.Data;
    using System;
    using System.Windows.Forms;

    public partial class Form1 : Form
    {
        private Form1ViewModel viewModel = new Form1ViewModel();
        private BindingManager bindingManager = new BindingManager();

        public Form1()
        {
            InitializeComponent();
            Load += OnLoad;
        }

        private void OnLoad(object sender, EventArgs eventArgs)
        {
            comboBox1.DataSource = viewModel.Roles;
            comboBox1.DisplayMember = "Name";
            comboBox1.ValueMember = "Name";

            bindingManager.Bindings.Add(new TypedBinding<TextBox, Form1ViewModel>(
                textBox1, t => t.Text, viewModel, v => v.Title));

            bindingManager.Bindings.Add(new TypedBinding<ComboBox, Form1ViewModel>(
                comboBox1, t => t.SelectedItem, viewModel, v => v.Role));
            //bindingManager.Bindings.Add(new TypedBinding<ComboBox, Form1ViewModel>(
            //    comboBox1, t => t.SelectedValue, viewModel, v => v.Title));

            viewModel.Role = viewModel.Roles[0];
        }
    }
}

Form1ViewModel.cs

namespace ComboApp1
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;

    public class Form1ViewModel : BusinessObject
    {
        public Form1ViewModel()
        {
            PopulateRoles();
        }

        private Role role;
        public Role Role
        {
            get { return role; }
            set
            {
                if (role != value)
                {
                    role = value;
                    OnPropertyChanged("Role");
                    Debug.WriteLine("Role: {0}{1}", role.Name, String.Empty);

                    Title = Role.Name;
                }
            }
        }

        private string title;
        public String Title
        {
            get { return title; }
            set
            {
                if (title != value)
                {
                    title = value;
                    OnPropertyChanged("Title");
                    Debug.WriteLine("Title: {0}{1}", title, String.Empty);
                }
            }
        }

        public List<Role> Roles { get; private set; }

        private void PopulateRoles()
        {
            Roles = new List<Role>();
            for (int i = 1; i <= 5; i++)
            {
                var role = new Role
                {
                    Name = String.Format("Role_{0}", i),
                    RoleGroup = String.Format("RoleGroup_{0}", i),
                    IsAdmin = false
                };
                role.Locations.Add("Location_{0}");
                Roles.Add(role);
            }
        }
    }
}

Role.cs

namespace ComboApp1
{
    using System;
    using System.Collections.Generic;

    public class Role
    {
        public Role()
        {
            this.IsAdmin = false;
            this.Locations = new List<string>();
        }

        public String Name { get; set; }
        public Boolean IsAdmin { get; set; }
        public String RoleGroup { get; set; }
        public List<String> Locations { get; private set; }

        public override string ToString()
        {
            return String.Format("WRBRBranchRole: {0}, IsAdmin: {1}, RoleGroup: {2}",
                this.Name, this.IsAdmin, this.RoleGroup);
        }
    }
}

BusinessObject.cs

namespace ComboApp1
{
    using System.ComponentModel;

    //base class for all business objects
    public abstract class BusinessObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            //thread safe
            PropertyChangedEventHandler handler;
            lock (this)
            {
                handler = PropertyChanged;
            }

            if (handler != null)
            {
                handler(this, e);
            }

            /*var handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, e);
            }*/
        }

        protected void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }
}

Form1.Designer.cs

namespace ComboApp1
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.textBox2 = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.SuspendLayout();
            // 
            // comboBox1
            // 
            this.comboBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.comboBox1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Location = new System.Drawing.Point(12, 38);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(282, 21);
            this.comboBox1.TabIndex = 0;
            // 
            // textBox1
            // 
            this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.textBox1.Location = new System.Drawing.Point(12, 12);
            this.textBox1.Name = "textBox1";
            this.textBox1.ReadOnly = true;
            this.textBox1.Size = new System.Drawing.Size(282, 20);
            this.textBox1.TabIndex = 1;
            // 
            // textBox2
            // 
            this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.textBox2.Location = new System.Drawing.Point(12, 168);
            this.textBox2.Name = "textBox2";
            this.textBox2.Size = new System.Drawing.Size(282, 20);
            this.textBox2.TabIndex = 2;
            // 
            // label1
            // 
            this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) 
            | System.Windows.Forms.AnchorStyles.Right)));
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 147);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(282, 13);
            this.label1.TabIndex = 3;
            this.label1.Text = "This TextBox lets you move the focus from the ComboBox.";
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(303, 200);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.textBox2);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.comboBox1);
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.ComboBox comboBox1;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.TextBox textBox2;
        private System.Windows.Forms.Label label1;
    }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.