Skip to content

fw2568/OpenUI5Sharp

 
 

Repository files navigation

OpenUI5Sharp

Built with Bridge.NET

OpenUI5Sharp is a C# Wrapper for OpenUI5, that uses Bridge.net to generate Javascript code, allowing you to generate OpenUI5 code using C#. OpenUI5Sharp also adds some features like typed object literals, typed parameters and other improvements thanks to the C# & Bridge combination.

Current Status

The current wrapper is based on OpenUI5 1.54.6 using Bridge.net 17.4.0 and the latest Retyped packages for libraries used by OpenUI5 (JQuery, QUnit, Sinon...).

OpenUI5 is quite large but all the libraries have been converted.

The following tutorials from the documentation are fully working and have been included as a reference on how to use OpenUI5Sharp:

  • Walkthrough (including unit and integration testing)
  • Data Binding
  • OData V4
  • Navigation and Routing

Also, the Shop Administration Tool demo application is fully working.

Bridge.net does not support OpenUI5 module loading (and probably never will) so currently we have to use a workaround for that.

XSD Schemas

SAP does not produces valid XSD schemas to have intellisense when editing XML views in Visual Studio or other editors that support XSD schemas. As it is really painful to work without valid XSD schemas, you can find my non official XSD schemas that work properly with Visual Studio 2017 in the folder XSDSchemas. However, keep in mind that OpenUI5 aggregations and associations do not work with a namespace different than the parent object making XML views sometimes invalid, but having the XSD schema is a big help.

A custom Visual Studio plugin will be needed to handle the validation properly (and also for things like binding expressions support, non sequencial schema elements, method generation, etc) but that is out of the scope of this project.

Examples

You can use OpenUI5Sharp with its more than 800 strongly typed object literals and its more than 200 strongly typed events and delegates, extra features like getPropertyFor, setPropertyFor, getParameterFor, etc by adding openui5sharp.min.js (11 KB to the page) and including the OpenUI5Sharp assembly to a project that uses Bridge.net.

Take a look at the four samples in the repository. They are straight conversions from the tutorials/demos of OpenUI5. There are two projects per tutorial. One is a web application and the other is the C# project that creates the realted client scripts using OpenUI5Sharp and Bridge. However, this samples only scratch the surface of what you can do with OpenUI5Sharp. The true potential of OpenUI5Sharp can be achieved with dynamically generated XML Views using ASP.NET, RESTier for OData V4, etc.

For those who want to see some sample code without downloading anything, here you have 3 pieces of code, first in Javascript using OpenUI5 and then in C# using OpenUI5Sharp.

This OpenUI5 javascript handler:

confirm: function (oEvent) {
    var oSortItem = oEvent.getParameter("sortItem");
    this._oRouterArgs.query.sortField = oSortItem.getKey();
    this._oRouterArgs.query.sortDescending = oEvent.getParameter("sortDescending");
    delete this._oRouterArgs.query.showDialog;
    oRouter.navTo("employeeOverview", this._oRouterArgs, true /*without history*/);
}

converts to this strongly typed event handler, where the parameters are retrieved using expressions and not string constants:

void confirm(sap.ui.@base.Event<sap.m.ViewSettingsDialog.ConfirmInfo> oEvent, object oData)
{
    var oSortItem = oEvent.getParameterFor(e => e.sortItem);
    this._oRouterArgs.sortField = oSortItem.getKey();
    this._oRouterArgs.sortDescending = oEvent.getParameterFor(e => e.sortDescending);
    this._oRouterArgs.showDialog = false;
    oRouter.navTo("employeeOverview", new { query = this._oRouterArgs }, true /*without history*/);
}

This javascript code gets/sets properties of a JSONModel:

onSort : function () {
	var oView = this.getView(),
		aStates = [undefined, "asc", "desc"],
		aStateTextIds = ["sortNone", "sortAscending", "sortDescending"],
		sMessage,
		iOrder = oView.getModel("appView").getProperty("/order");

	iOrder = (iOrder + 1) % aStates.length;
	var sOrder = aStates[iOrder];

	oView.getModel("appView").setProperty("/order", iOrder);
	oView.byId("peopleList").getBinding("items").sort(sOrder && new Sorter("LastName", sOrder === "desc"));

	sMessage = this._getText("sortMessage", [this._getText(aStateTextIds[iOrder])]);
	MessageToast.show(sMessage);
},

The equivalent code in OpenUI5Sharp uses a strongly typed JSONModel with no magic strings and type conversions for the properties:

public void onSort()
{
    var oView = this.getView();
    string[] aStates = new string[] { null, "asc", "desc" };
    string[] aStateTextIds = new string[] { "sortNone", "sortAscending", "sortDescending" };
    string sMessage;
    int iOrder = oView.getModelFor<ViewModel>("appView").getPropertyFor(m => m.order);

    iOrder = (iOrder + 1) % aStates.Length;
    var sOrder = aStates[iOrder];

    oView.getModelFor<ViewModel>("appView").setPropertyFor(m => m.order, iOrder);
    if (sOrder != null) {
        oView.byId("peopleList").getBinding<sap.ui.model.odata.v4.ODataListBinding>("items").sort(new sap.ui.model.Sorter("LastName", sOrder == "desc"));
    } else {
        oView.byId("peopleList").getBinding<sap.ui.model.odata.v4.ODataListBinding>("items").sort();
    }

    sMessage = this._getText("sortMessage", new string[] { this._getText(aStateTextIds[iOrder]) });
    sap.m.MessageToast.show(sMessage);
}

The following javascript uses object literals for the metadata:

sap.ui.define([
    "sap/ui/core/Control",
    "sap/m/RatingIndicator",
    "sap/m/Label",
    "sap/m/Button"

], function (Control, RatingIndicator, Label, Button) {
    "use strict";
    return Control.extend("sap.ui.demo.walkthrough.control.ProductRating", {
        metadata: {
            properties: {
                value: { type: "float", defaultValue: 0 }
            },
            aggregations: {
                _rating: { type: "sap.m.RatingIndicator", multiple: false, visibility: "hidden" },
                _label: { type: "sap.m.Label", multiple: false, visibility: "hidden" },
                _button: { type: "sap.m.Button", multiple: false, visibility: "hidden" }
            },
            events: {
                change: {
                    parameters: {
                        value: { type: "int" }
                    }
                }
            }
        },
        init: function () {
            this.setAggregation("_rating", new RatingIndicator({
                value: this.getValue(),
                iconSize: "2rem",
                visualMode: "Half",
                liveChange: this._onRate.bind(this)
            }));
            this.setAggregation("_label", new Label({
                text: "{i18n>productRatingLabelInitial}"
            }).addStyleClass("sapUiSmallMargin"));
            this.setAggregation("_button", new Button({
                text: "{i18n>productRatingButton}",
                press: this._onSubmit.bind(this)
            }).addStyleClass("sapUiTinyMarginTopBottom"));
        },

The equivalent code in OpenUI5Sharp uses strongly typed metadata and strongly typed settings:

[FileName("control/ProductRating.js")]
[Name("sap.ui.demo.walkthrough.control.ProductRating")]
public class ProductRating : sap.ui.core.Control
{
        
    [Constructor("{}")]
    public class RatingInfo
    {
        public float value;
    }

    [Init(InitPosition.Bottom)]
    public static void Script()
    {
        sap.ui.define(new string[] {
                "sap/ui/core/Control",
                "sap/m/RatingIndicator",
                "sap/m/Label",
                "sap/m/Button"
            },
            new Func<object>(
                () => {
                    var metadata = new Metadata() {
                        properties = new Map<Union<string, PropertyInfo>>() {
                            { "value", new PropertyInfo() { type = "float", defaultValue = 0 }}
                        },
                        aggregations = new Map<Union<string, AggregationInfo>>() {
                            { "_rating", new AggregationInfo() { type = "sap.m.RatingIndicator", multiple = false, visibility = "hidden" }},
                            { "_label", new AggregationInfo() { type = "sap.m.Label", multiple = false, visibility = "hidden" }},
                            { "_button", new AggregationInfo() { type = "sap.m.Button", multiple = false, visibility = "hidden" }}
                        },
                        events = new Map<Union<string, EventInfo>>() {
                            { "change", TypedMetadata.CreateUI5EventInfo<RatingInfo>() }
                        }
                    };
                    var newObj = Glue.CreateRawClassObject<ProductRating>(metadata);
                    return sap.ui.core.Control.extend(nameof(ProductRating), newObj);
                }
            )
        );
    }

    public override void init()
    {
        this.setAggregation("_rating", new sap.m.RatingIndicator(new sap.m.RatingIndicator.Settings() {
            value = this.getProperty<float>("value"),
            iconSize = "2rem",
            visualMode = "Half",
            liveChange = _onRate,
        }));
        this.setAggregation("_label", new sap.m.Label(new sap.m.Label.Settings() {
            text = "{i18n>productRatingLabelInitial}"
        }).addStyleClass("sapUiSmallMargin"));
        this.setAggregation("_button", new sap.m.Button(new sap.m.Button.Settings() {
            text = "{i18n>productRatingButton}",
            press = _onSubmit
        }).addStyleClass("sapUiTinyMarginTopBottom"));
    }

Also notice that event parameters are generated automatically from the class RatingInfo.

History

2018/06/15 - v1.0.0 - Initial version.

2018/10/09 - v1.1.0 - Beta version.

What's new in this release:

  • Added support for the rest of OpenUI5 libraries.
  • Renamed the parent namespace to UI5 in case some day SAPUI5Sharp gets released.
  • Added Shop Administration Tool demo application.
  • A lot of minor fixes and API improvements.
  • Improved unit and integration test support.

Contact

OpenUI5Sharp is developed by Manuel Abadía.

You can contact me creating a new issue or sending me an email to [my github username] @ gmail DOT com

License

This project is licensed under the GPL3 License. See the LICENSE file for details.

About

A C# Wrapper for OpenUI5 using Bridge.net

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 56.8%
  • C# 43.2%