Archive

Archive for the ‘Exploring the CodeFluent Runtime’ Category

Template Engine and Extensibility

June 11, 2014 Leave a comment

A few time ago, we presented the CodeFluent Runtime’s Template Engine. Today we’ll see how to extend it to change a little bit its syntax and to add custom keywords.

Here is a simple template:

<% var now = new Date(); %>
Hello <%= Name %>!
It's <%= now.toDateString() %>
Cheers,
<%= CurrentUser %>

To use the standard Template Engine, we use this following code:

Template template = new Template();

template.LoadText(templateText, "Name", "CurrentUser");
string templateResult = template.Run(new Dictionary<string, object>
{
     { "Name", "Jone Doe" }, 
     { "CurrentUser", Environment.UserName }
}); 

Console.WriteLine(templateResult);

This will output:

Hello Jone Doe!
It’s Thu Mar 6 2014
Cheers,
The R&D Team

After some customization, the template will be more readable:

Hello {{Name}}!
It's {{Now:yyyy/MM/dd}}
Cheers,
{{CurrentUser}}

Before extending the template engine we have to understand how it works. The engine is composed of 4 classes:

  • Template: contains the configuration such as delimitation tokens and methods to load and run the template
  • ParsedTemplate: contains parameters and code or text blocks extracted while parsing the template
  • ParsedBlock / CodeBlock: contains block text and a method to transform it into JavaScript code
  • Output: contains methods to write into the output file

Let’s use the first sample to understand. First, it will parse the template and extract the following blocks:

  • CodeBlock: var now = new Date();
  • TextBlock: Hello
  • CodeBlock: = Name
  • TextBlock: It’s
  • CodeBlock: = now.toDateString()

Then it will transform blocks into JavaScript instructions. These Text blocks are transformed into “Output.Write(block content)”. When code block starts with “=” it will generate “Output.Write(parameterName)”, otherwise the JavaScript is written as is.

The generated JavaScript is:

ActiveXObject=null;
function __run(Output, Name, CurrentUser) {
 var now = new Date(); 
Output.WriteBlock(1);
Output.Write( Name );
Output.WriteBlock(3);
Output.Write( now.toDateString() );
Output.WriteBlock(5);
Output.Write( CurrentUser );
}

Now we understand the template engine, let’s extend it.
We would like to change to {{ and }}. To do so, we extend the Template class.

public class CustomTemplate : Template
{
    public CustomTemplate()
    {
        StartToken = "{{";
        EndToken = "}}";
    }
}

We also need to create a new CodeBlock to parse the content and write the appropriate JavaScript code:

public class CustomCodeBlock : CodeBlock
{
    public string Format { get; private set; }
    public string ArgumentName { get; private set; }

    public CustomCodeBlock(string code, int creationIndex)
        : base(code, creationIndex)
    {
        Parse(code);
    }

    private void Parse(string text)
    {
        if (text == null || text.StartsWith("="))
            return;

        string argumentName = text;
        string format = null;
        int formatIndex = text.IndexOf(":");
        if (formatIndex > 0)
        {
            argumentName = text.Substring(0, formatIndex);
            format = text.Substring(formatIndex + 1);
        }

        ArgumentName = argumentName;
        Format = format;
    }

    public override void BuildSourceCode(StringBuilder source, ParsedTemplate parsed)
    {
        if(!string.IsNullOrEmpty(ArgumentName))
        {
            source.Append(parsed.Template.OutputItemName);
            if (string.IsNullOrEmpty(Format))
            {
                source.Append(".Write(");
                source.Append(ArgumentName);
                source.Append(");");
            }
            else
            {
                source.Append(".WriteFormatted(");
                source.Append(ArgumentName);
                source.Append(", \"");
                source.Append(Format);
                source.Append("\");");
            }

            return;
        }

        base.BuildSourceCode(source, parsed);
    }
}

Now we have to create the WriteFormatted function in the Output class:

[ComVisible(true)] // Needed to be used by JavaScript code
public class CustomOutput : Output
{
    public CustomOutput(ParsedTemplate template, TextWriter writer)
        : base(template, writer)
    {

    }

    public void WriteFormatted(object value, string format)
    {
        if (string.IsNullOrWhiteSpace(format))
        {
            Write(string.Format("{0}", value));
        }
        else
        {
            string formattedValue = string.Format("{0:" + format + "}", value);
            Write(formattedValue);
        }
    }
}

Finally let’s say to the Template to use our custom classes instead of the default ones.

public class CustomTemplate : Template
    {
        public override CodeBlock CreateNewCodeBlock(string code, int creationIndex)
        {
            return new CustomCodeBlock(code, creationIndex);
        }

        public override Output CreateNewOutput(ParsedTemplate parsedTemplate, TextWriter writer)
        {
            return new CustomOutput(parsedTemplate, writer);
        }
    }

That’s it! The full sample is available on our GitHub.

Happy Templating

The R&D Team.

How to compress or extract CAB archives?

June 2, 2014 1 comment

Today, on the series “Exploring the CodeFluent Runtime” we’re going to explore how to compress or extract CAB archives.

Cabinet (or CAB) is an archive file format for Windows that supports lossless data compression and embedded digital certificates used for maintaining archive integrity. Cabinet files have .cab file name extensions.

First, we have to add a reference to “CodeFluent.Runtime.dll”. The namespace we’ll use is “CodeFluent.Runtime.Compression”, the same as for compressing or extracting ZIP file.

One of the biggest advantage compare to ZIP file, is that it can work in memory or by using the file system as it uses Stream. The second point is you don’t have to add a native DLL: it’s all managed. While it’s less efficient than a native implementation, it’s easier to deploy.

Here’s an example to compress one file and a directory:

using (MemoryStream stream = new MemoryStream())
{
    using (CabFile file = new CodeFluent.Runtime.Compression.CabFile(stream, CabFileMode.Compress))
    {
        file.CompressionLevel = CabCompressionLevel.Maximum;
        file.AddEntry("File.txt");
        file.AddDirectory("Sample");
    }
}

Extracting files is as simple as compressing.

using (CabFile file = new CodeFluent.Runtime.Compression.CabFile(stream, CabFileMode.Decompress))
{
    file.EntryExtracted += (sender, e) =>
    {
        //e.Entry.Name
        //e.Entry.OutputStream
        //e.Entry.Bytes
        //e.Entry.Size
        //e.Entry.LastWriteTime
        //e.Entry.Tag
    };
    file.ExtractEntries();
}

And there’s more…

We add a method to determine the compression method (CAB or ZIP) of a file. This method can use the file extension if available or the first four bytes of the file (i.e. magic number):

CompressionUtilities.SniffFileFormat("test.cab", useExtensionAsHint: true) == CompressionFileFormat.Cab

And that’s not all, in the previous article, we wrote about how to sign a file by using the runtime. CAB file can also be signed, so let sign it:

X509Certificate2 certificate = Authenticode.FindSuitableCertificate(); 
Authenticode.SignFile(certificate, "test.cab", null, "SoftFluent");

Cab properties

Happy compressing and signing,

The R&D Team

Exploring the CodeFluent Runtime: Authenticode


Today, on the series “Exploring the CodeFluent Runtime” we’re going to explore how to sign an application with Authenticode method.

Microsoft Authenticode, which is based on industry standards, allows developers to include information about themselves and their code with their programs through the use of digital signatures. Authenticode allows software vendors to sign:

  • .cab files
  • .cat files
  • .ctl files
  • .dll files
  • .exe files
  • .ocx files

First we need a certificate that allows Code Signing. If you haven’t one, let’s create a self-signed one:

REM May change depending of your installed Windows SDK
cd "C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin"

REM Generate the root certificate
.\makecert.exe -r -pe -n "CN=Sample.CA" -ss CA -sr CurrentUser -a sha1 -cy authority -sky signature -sv d:\Sample.CA.pvk d:\Sample.CA.cer

REM Add the Root certificate to the user store
certutil.exe -user -addstore Root d:\Sample.CA.cer

REM Create the certificate for code signing
.\makecert.exe -pe -n "CN=Sample.CodeSigning" -eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" -a sha1 -cy end -sky signature -ic d:\Sample.CA.cer -iv d:\Sample.CA.pvk -sv d:\Sample.CodeSigning.pvk d:\Sample.CodeSigning.cer

REM Convert to certificate to pfx file format
.\pvk2pfx.exe -pvk d:\Sample.CodeSigning.pvk -spc d:\Sample.CodeSigning.cer -pfx d:\Sample.CodeSigning.pfx

We can now sign a file. Add the “CodeFluent.Runtime.dll” reference and use the following code:

X509Certificate2 certificate = Authenticode.FindSuitableCertificate();
Authenticode.SignFile(certificate, "sample.exe", null, "SoftFluent");

The first line find a valid certificate for code signing in the user certificate store. If none is found, it returns null.

The second line signs the file. You have to indicate:

  • the certificate to use
  • the file to sign
  • the timestamp server
  • the display name

If you look at the file properties, you’ll find a new tab ‘Digital Signature’ which contains details about the signer.

Digital Signature

Please note:

  • you don’t need to provide a password, nor a path to the certificate => Generic, simple and secure
  • the method doesn’t rely on the Windows SDK, so you don’t have to bother with SDK path => much simplier :)
  • it’s a DLL so it’s very easy to integrate in your application

Additionally you’ll find two methods:

//Determines whether the specified certificate can sign code.
public static bool CanSignCode(X509Certificate2 certificate)

//Determines whether the specified file is signed using authenticode.
public static bool IsSigned(string filePath)

Happy authenticoding,

The R&D team

Exploring the CodeFluent Runtime: Web Controls – Part 2

February 5, 2014 1 comment

In Part 1 of this series, we looked at some useful controls from the CodeFluent.Runtime.Web assembly.
On the same subject, we’ll explore in this post some other very useful controls for ASP.NET WebForms application.

The first controls are DataSource controls; They aren’t visual but very convenient as they can be bound to any DataBound controls like GridView, ListView, etc.

CountryDataSource (CodeFluent.Runtime.Web.UI.CountryDataSource) gives you a list of countries with a lot of properties, including localization information (EnglishName, NativeName, Location, Region, etc.). The type of the enumerated item is CodeFluent.Runtime.Utilities.Country. You can learn more about this type in the related article on our blog.

<cfe:CountryDataSource ID="CountryDataSource1" runat="server"/>
<asp:GridView ID="GridView2" runat="server" DataSourceID="CountryDataSource1" AllowPaging="true">

CountryDataSource

CultureDataSource (CodeFluent.Runtime.Web.UI.CultureDataSource) gives you a list of CultureInfo (System.Globalization.CultureInfo) and can be bound with any DataBoundControl (GridView, DropDownList…).

<cfe:CultureDataSource ID="CultureDataSource1" runat="server" />
<asp:GridView ID="GridView3" runat="server" DataSourceID="CultureDataSource1" AllowPaging="true">

CultureDataSource

CodeFluent Entities comes with another cool Web Control: the CultureDropDownList.

CultureDropDownList (CodeFluent.Runtime.Web.UI.WebControls.CultureDropDownList) displays automatically for you a DropDownList filled with cultures. With a single line of code, you can let the user change the UI Culture of your website.
First, add this control to your page:

<cfe:CultureDropDownList id="cultures" runat="server" CultureCookieName="culture" AutoPostBack="true" TitleMemberName="EnglishIEStyle" TextMemberName="NativeName" CultureList="en-us;fr-fr" />

The CultureList property lets you set the cultures you want to display. By default, all available cultures (on the current computer) are loaded.

Then, just add the following code in the Global.asax file.

protected void Application_AcquireRequestState(object sender, EventArgs e)
{
    CultureDropDownList.SetRequestCulture(Request, "culture"); 
}

The second parameter corresponds to the name of the cookie set in the CultureDropDownList in the page.

Because the CultureDropDownList control is set to AutoPostBack=”true”, when the user selects another culture, the website page will automatically reload with the selected culture. Of course, you need to put in place the ASP.NET globalization mechanism and provide the corresponding resources files :).

FreeForm Control
Now, another topic. Let’s imagine you have several forms to implement as pages on your site, most of them used to get simple input from your users. Let’s suppose you want to send email with the content of the forms. This can be useful for polls for example.

For this, you can use the FreeForm control (CodeFluent.Runtime.Web.UI.WebControls.FreeForm). It allows you to create an arbitrary form, add all the child controls you want to it and then add a piece of code to gather all the user input data. Here is a quick example.

We start with a simple markup:

<cfe:FreeForm ID="FF" runat="server" OnFormChanged="OnFormChanged" DecamelizeOptions="Default" >
    <ItemTemplate>
        <asp:Panel ID="Panel3" runat="server" GroupingText="Personnal Information">
            <asp:Label ID="Label1" runat="server" Text="Preferred Name:" /><br />
            <asp:TextBox ID="TextBox1" runat="server" Text='<%#Bind("PreferredName") %>' /><br />
            <asp:Label ID="Label2" runat="server" Text="City:" /><br />
            <asp:TextBox ID="TextBox3" runat="server" Text='<%#Bind("City") %>' /><br />
        </asp:Panel>
        <asp:Panel ID="Panel4" runat="server" GroupingText="Business Information">
            <asp:Label ID="Label3" runat="server" Text="Your Company:" /><br />
            <asp:TextBox ID="TextBox4" runat="server" Text='<%#Bind("YourCompany") %>' /><br />
            <asp:Label ID="Label4" runat="server" Text="Describe your primary role and function:" /><br />
            <asp:TextBox ID="TextBox5" runat="server" Text='<%#Bind("DescribeYourPrimaryRole_x0026_Function") %>' /><br />
        </asp:Panel>
        <br />
        <asp:Button ID="Button2" runat="server" Text="OK" />
    </ItemTemplate>
</cfe:FreeForm>

We have a form with 4 textboxes and their corresponding labels into 2 panels, plus a standard button to submit :

When the user submits the button, the whole input data will be transformed into a dictionary instance automatically. Each control will provide a dictionary entry in that instance. Notice that all the Text attributes of the textboxes have a standard ASP.NET bind token attached. That token will become the entry field key, and the entry value will be the data entered by the user (whatever the type of this data and the type of the control). To get this dictionary you just need to attach to the FormChanged event and read the Values property of the FormChangedEventArgs parameter, like this:

<script runat="server">
    protected void OnFormChanged(object sender, FormChangedEventArgs e)
    {
        StringBuilder sb = new StringBuilder();

        foreach (DictionaryEntry de in e.Values)
        {
            sb.AppendLine(de.Key + "=" + de.Value + "<br/>");
        }
        
        // NOTE: instead, send email here with the content of the StringBuilder
        litResult.Text = sb.ToString();
    }
</script>     

You may have noticed that we have defined the field names using camel-case and also some weird hexadecimal notation. The FreeForm control has the ability to “decamelize” these keys and unescape the Unicode characters represented by their hexadecimal values. This trick allows us to use anything for key names (although the Bind syntax is much more restrictive). You can define several options in the DecamelizeOption attribute (None, ForceFirstUpper, ForceRestLower, UnescapeUnicode, UnescapeHexadecimal, ReplaceSpacesByUnderscore, ReplaceSpacesByMinus, ReplaceSpacesByDot, KeepFirstUnderscores, DontDecamelizeNumbers, KeepFormattingIndices).

So, this simple example gives you the following result:

Of course, you will hopefully implement something more useful in your project :) You can also imagine having a form generator for power-users, letting them design simple forms and process the Key/Value Dictionary generated by the FreeForm control in a pretty much automatic way.

NumericTextBox Control
Do you need a numeric-only textbox input?. CodeFluent.Runtime.Web has a solution for you: the NumericTextBox control.

The NumericTextBox control (CodeFluent.Runtime.Web.UI.WebControls.NumericTextBox) prevents user from entering non-numeric characters. You can define the value type with the TargetTypeName attribute, define the MaximumNumbers, MaximumIntegerNumbers, MaximumDecimalNumbers or the Negative or Positive Sign. Note this control can be used inside a FreeForm control we say previously.

<cfe:NumericTextBox ID="NumericTextBox1" runat="server" Value='<%# Bind("NumberOfEmployees") %>' TargetTypeName="System.Int32" />

There is also associated DataControlField, NumericTextField CodeFluent.Runtime.Web.UI.WebControls.NumericTextField) fields controls that you can use in GridView, DetailsView, etc.

<cfe:NumericTextField DataField="Age" HeaderText="Age" TargetTypeName="System.Int32"/>

Captcha Control
The Captcha control (CodeFluent.Runtime.Web.UI.WebControls.CaptchaControl) displays an image with some simple text inside, but supposedly quite difficult to read for machines. You can define the image size, the complexity of the produced image, and a timeout duration. Notice that the image is generated by the BinaryLargeObjectHttpHandler of CodeFluent Entities (Learn more about Blob here).

The Captcha control comes with its validator, the CaptchaValidator control (CodeFluent.Runtime.Web.UI.WebControls.CaptchaValidator). As any validator, you just need to declare the ControlToValidate and the CaptchaControlID associated.

In this example, we just display a message if the text entered corresponds to what was generated by the Captcha control.

<cfe:CaptchaControl ID="CaptchaControl1" runat="server" Width="200px" Height="50px" Expiration="120"
    Options="FontWarpFactorMedium, BackgroundNoiseLevelHigh,LineNoiseLevelHigh" />
<br />
Please enter the code or press F5 to refresh the browser
<br />
<cfe:CaptchaValidator ID="CaptchaValidator1" runat="server" ControlToValidate="Verify" CaptchaControlID="CaptchaControl1"
    SetFocusOnError="True" ErrorMessage="The code doesn’t match or there was a timeout" ForeColor="Red" />
<br />
<asp:TextBox ID="Verify" runat="server" EnableViewState="False" AutoCompleteType="None" />
<asp:Button ID="btValidate" runat="server" Text="Validate" OnClick="btValidate_Click" /><br />
<asp:Label ID="lblResult" runat="server" Text="You enter the correct text! Thank you for validating." Visible="false" ForeColor="Green"/>

In the button Click event, call Page.IsValid to validate the captcha:

<script runat="server">
    protected void btValidate_Click(object sender, EventArgs e)
    {
        if (Page.IsValid)
        {
            lblResult.Visible = true;
        }
        else
        {
            lblResult.Visible = false;
        }
    }
</script> 

Have a look at the Captcha image here:

Captcha

As you’ve seen in this serie, CodeFluent.Runtime.Web can be very useful to us, web developers who are tired to write a lot of code-behind to do simple actions. With these controls you just need to drag and drop them on your page, save and enjoy.

These controls are located in the CodeFluent.Runtime.Web assembly, part of the CodeFluent Entities product ! Try them!

Happy controling!

The R&D team.

Exploring the CodeFluent Runtime: Web Controls – Part 1

January 28, 2014 1 comment

Today, on the series “Exploring the CodeFluent Runtime” we’re going to explore the ASP.Net Web Controls inside the CodeFluent.Runtime.Web namespace. This is all provided as part of CodeFluent Entities.

In the CodeFluent.Runtime.Web assembly, you’ll find several controls usable in ASP.Net WebForms applications. The first we’ll see are controls used to render UI relatively to the data (bindings).

BooleanControl (CodeFluent.Runtime.Web.UI.WebControls.BooleanControl) displays what’s defined in FalseTemplate or TrueTemplate according to a boolean value.

<cfe:BooleanControl ID="BooleanControl1" runat='server' Value='<%# Eval("MyBooleanValue") %>' AutoBind="true">
    <TrueTemplate>
        This template will be displayed if Value is evaluated as "true"
    </TrueTemplate>
    <FalseTemplate>
        This template will be displayed if Value is evaluated as "false"
    </FalseTemplate>
</cfe:BooleanControl>

CompareControl (CodeFluent.Runtime.Web.UI.WebControls.CompareControl) displays FalseTemplate or TrueTemplate according to what’s defined by the ValueToCompare attribute and an Operator (Equal, NotEqual,
GreaterThan, GreaterThanEqual, LessThan, LessThanEqual, DataTypeCheck). For the DataTypeCheck operator, the ValueToCompare will be the full name of the type to check.

<cfe:CompareControl ID="CompareControl1" runat='server' Value='<%# Eval("MyValueToCompare") %>' Operator="GreaterThan" ValueToCompare="0">
    <TrueTemplate>
        Value is greater than 0
    </TrueTemplate>
    <FalseTemplate>
        Value is less than or equal to 0
    </FalseTemplate>
</cfe:CompareControl>
 
<cfe:CompareControl ID="CompareControl2" runat='server' Value='<%# Eval("MyValueToCompare") %>' Operator="DataTypeCheck" ValueToCompare="System.Int32">
    <TrueTemplate>
        Value is a System.Int32
    </TrueTemplate>
    <FalseTemplate>
        Value is not a System.Int32
    </FalseTemplate>
</cfe:CompareControl>

MultiCompareControl (CodeFluent.Runtime.Web.UI.WebControls.MultiCompareControl) is similar to the CompareControl but is more like a switch.

<cfe:MultiCompareControl ID="MultiCompareControl1" runat="server" Value='<%#Eval("MyValueToMultiCompare") %>'>               
    <case ValueToCompare="10" Operator="GreaterThan">
            Value is greater than 10
    </case>
    <case ValueToCompare="0">
    Value is equal to 0
    </case>
    <default>
    Value is not equal to 0 and is less than or equal to 10
    </default>
</cfe:MultiCompareControl>

ExistsControl (CodeFluent.Runtime.Web.UI.WebControls.ExistsControl) displays FalseTemplate or TrueTemplate depending on a given value. The value is tested against “null”, “DBNull”, or an empty string (possibly trimmed).

<cfe:ExistsControl ID="ExistsControl1" runat='server' Value='<%# Eval("Email") %>' Trim="true">
    <TrueTemplate>
        This template is displayed only if Value is not null or empty 
    </TrueTemplate>
    <FalseTemplate>
        This template is displayed when Value is null
    </FalseTemplate>
</cfe:ExistsControl>

When you work with enumerations into your Model, you want to be able to display and edit them easily into your forms or GridView. We have a solution for you! Let me introduce the Enum Controls.

EnumCheckBoxList (CodeFluent.Runtime.Web.UI.WebControls.EnumCheckBoxList) derives from the standard CheckBoxList control but is automatically filled with the fields of the enumeration type you define EnumTypeName parameter. Note this also supports multi-valued enumerations (with a [Flags] custom attribute).

EnumRadioButtonList (CodeFluent.Runtime.Web.UI.WebControls.EnumRadioButtonList) derives from the standard RadioButtonList control. As the EnumCheckBox, you only need to define the EnumTypeName attribute

EnumDropDownList (CodeFluent.Runtime.Web.UI.WebControls.EnumDropDownList) derives from the standard DropDownList and works the same way.

Another control that allows you to quickly bind your data is the BoolControl (CodeFluent.Runtime.Web.UI.WebControls.BoolControl). The BoolControl is a visual custom control that displays a System.Boolean or Nullable<System.Boolean> bound value. Depending whether the value is nullable or not, it can display a True/False or True/False/Undefined visual. It can use a CheckBox, DropDownList, horizontal button list, ListBox or horizontal or vertical radio button list to display these 2 or 3 items. It also supports read-only rendering and custom texts, interesting for localization purposes.

Is Customer:

<cfe:BoolControl ID="BoolControl1" runat="server" Value='<%# Bind("IsCustomer") %>' TrueText="Yes" FalseText="No" UnspecifiedText="Undefined" BoolControlType="HorizontalRadioButtonList" />

Contact Method:

<cfe:EnumCheckBoxList ID="EnumCheckBoxList1" runat="server" Value='<%# Bind("MethodToContact") %>' EnumTypeName="BlogCFE.ContactManager.ContactMethod" />
Origin (RadioButton):
<cfe:EnumRadioButtonList ID="EnumRadioButtonList1" runat="server" Value='<%# Bind("Origin") %>' EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />
Origin (DropDown):
<cfe:EnumDropDownList ID="EnumDropDownList1" runat="server" Value='<%# Bind("Origin") %>' EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />           

Here is the result:

For each of these controls, an associated DataControlField exists so you can use them in GridView, DetailsView, etc.

<cfe:BoolField DataField="IsCustomer" HeaderText="Is Customer" TrueText="Yes" FalseText="No" BoolControlType="DropDownList" />
<cfe:EnumCheckBoxListField DataValueField="MethodToContact" HeaderText="Contact method" EnumTypeName="BlogCFE.ContactManager.ContactMethod" />
<cfe:EnumRadioButtonListField DataValueField="Origin" HeaderText="Origin (RadioButton)" EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />
<cfe:EnumDropDownListField DataValueField="Origin" HeaderText="Origin (DropDown)" EnumTypeName="BlogCFE.ContactManager.ContactOrigin" />        

the result in a grid view:

List of Contacts

As you’ve seen, these controls can avoid you to write a lot of code focusing more on a declarative way of programming.

In the next article, we’ll introduce the DataSources controls and another couple of cool utilities.

The R&D team.

Exploring the CodeFluent Runtime: Country utilities

January 21, 2014 1 comment

The CodeFluent.Runtime.Utilities.Country class is a cool tool that provides information about countries, regions, geographic locations and currencies.

Below is a figure showing a WPF application with a DataGrid that contains a list of countries with the information this class provides: locale identifier, region, english name, native name (in the corresponding language), currencies, etc.)

Country

XAML :

<Grid>
    <DataGrid x:Name="MyDataGrid" />
</Grid>

C# :

MyDataGrid.ItemsSource = CodeFluent.Runtime.Utilities.Country.AllCountries;

By running the code above, you’ll get a list of countries as a data source for your WPF DataGrid.

The Country object also exposes some useful methods such as:

GetCountry : find a country by its ISO-3166 two-letter code

CodeFluent.Runtime.Utilities.Country.GetCountry("AL")

It also supports principal subdivisions (e.g., provinces or states) of all countries coded in ISO 3166 so you can get locations and not only countries:

// *private joke* Carl, this one's for you !
var guadeloupe = CodeFluent.Runtime.Utilities.Country.GetCountry("GL");

// Get all locations installed on your system.
var allLocations = CodeFluent.Runtime.Utilities.Country.AllLocations;

GetCurrencyCountries : find countries for a given ISO currency symbol

var euroCountries = CodeFluent.Runtime.Utilities.Country.GetCurrencyCountries("EUR")

So here is the same grid with the list of countries that use EURO currency:

Country

Before leaving this topic, I suggest you have also have a look at the CultureComboBox control available in the CodeFluent.Runtime.Design namespace. It provides an associated Winforms ComboBox specialized for displaying countries.

The CodeFluent Runtime is  available with the full CodeFluent Entities product and with the CodeFluent Runtime Client 100% free assembly (available directly from Nuget).

Happy countrying!

The R&D team.

Exploring the CodeFluent Runtime: The Ribbon Control

January 17, 2014 Leave a comment

Hey, unless you lived on another planet the last 7 years, you guys should know what is a Ribbon is in terms of user interface. It’s a sophisticated set of toolbars and buttons placed on several tabs that allows you to quickly find the commands to complete a task. Since the release of Microsoft Office 2007 (Word, Excel, PowerPoint), this kind of control has become greatly appreciated by developers to provide a great user experience to their applications.

Office Ribbon

Office Ribbon

Now, the free CodeFluent Runtime Client Library that we, at SoftFluent, provide, will allow us to easily integrate a similar control in your Windows Forms applications. First of all, just take a look at the following screenshot of this RibbonControl schema:

RibbonControl01

The RibbonControl consists of different tabs called RibbonTab (crazy huh?). Each tab (as ‘Home’ and ‘View’ above) can include one or several groups of controls of RibbonPanel type (as ‘Clipboard’, ‘Font’, ‘Paragraph’, and ‘Insert’ above). Each panel consists of a list of RibbonItems objects (RibbonItem is not a control, it’s just a wrapper object). Each RibbonItem can embed standard controls such as a Button or a DropDownList.

Now, I’m going to explain how to create the RibbonControl introduced above programmatically (as of today, we don’t provide a cool Visual Studio designer integration, so this is in fact the only way to use this control…)

Add a RibbonControl in a Windows form (Winforms technology) :

The first easy step is to add a RibbonControl, in the same way that you would add a button to a form. The RibbonControl inherits from the Control class:

var ribbonControl1 = new CodeFluent.Runtime.Design.RibbonControl();

this.Controls.Add(ribbonControl1);

Add RibbonTabs to RibbonControl:

var homeTab = new CodeFluent.Runtime.Design.RibbonTab("Home");
var viewTab = new CodeFluent.Runtime.Design.RibbonTab("View");

ribbonControl1.Tabs.Add(homeTab);
ribbonControl1.Tabs.Add(viewTab);

Add RibbonPanel to RibbonTab:

var clipBoardPanel = new CodeFluent.Runtime.Design.RibbonPanel("Clipboard");
var fontPanel = new CodeFluent.Runtime.Design.RibbonPanel("Font");
var paragraphPanel = new CodeFluent.Runtime.Design.RibbonPanel("Paragraph");
var insertPanel = new CodeFluent.Runtime.Design.RibbonPanel("Insert");

homeTab.Panels.Add(clipBoardPanel);
homeTab.Panels.Add(fontPanel);
homeTab.Panels.Add(paragraphPanel);
homeTab.Panels.Add(insertPanel);

Here is the result:
RibbonControl03

Add RibbonItem to RibbonPanel:
Finally, we add some standard controls to the RibbonPanel :

var copyButton = new CodeFluent.Runtime.Design.RibbonButton("Copy");
copyButton.Mode = CodeFluent.Runtime.Design.RibbonItemMode.Icon;
copyButton.IconIndex = 0;

var pasteButton = new CodeFluent.Runtime.Design.RibbonButton("Paste");
pasteButton.Mode = CodeFluent.Runtime.Design.RibbonItemMode.Icon;

var pasteOptionDdl = new CodeFluent.Runtime.Design.RibbonDropDownList("Paste options");

pasteOptionDdl.Items.Add(new CodeFluent.Runtime.Design.RibbonDropDownItem("Paste"));
pasteOptionDdl.Items.Add(new CodeFluent.Runtime.Design.RibbonDropDownItem("Paste special"));
clipBoardPanel.Items.Add(copyButton);
clipBoardPanel.Items.Add(pasteButton);
clipBoardPanel.Items.Add(pasteOptionDdl);

Just compile your code to get the desired result :

RibbonControl03

RibbonControl provides an ImageList property that can’store all the icons we need (such as ‘Copy’ / ‘Paste’ buttons here). So, for example, we can add two images to our Windows Forms project and to the image collection (ImageList) of the RibbonControl:

ribbonControl1.ImageList = new ImageList();
ribbonControl1.ImageList.ImageSize = new System.Drawing.Size(32, 32);

ribbonControl1.ImageList.Images.Add(Image.FromFile(@"Images\copyButtonIcon.png"));
ribbonControl1.ImageList.Images.Add(Image.FromFile(@"Images\pasteButtonIcon.png"));

To assign one of these icons to RibbonItem, simply assign the RibbonItem’s IconIndex property, which corresponds to the index of an image in this list:

pasteButton.IconIndex = 1;

Note that you can also resize all images in the collection this way :

ribbonControl1.ImageList.ImageSize = new System.Drawing.Size(32, 32);

In order to handle different sizes of icons, the RibbonControl exposes a second image collection, the SmallImageList. To assign an icon of this collection, just use the SmallIconIndex property.

Convenient and easy, don’t you think ?

Add RibbonControl in WPF application

Since WPF day one, it’s possible to host Windows Forms controls in your WPF application. So, if you need to use the RibbonControl in xaml, check out this article.

There are expensive ribbon controls out on the market offering much more features than this one.  Its main advantage is it’s simple and … free. This control is provided 100% free of charge. Its license is tied to the CodeFluent Runtime Client license (which basically allows you to do anything with it…). The support is provided on a best-effort basis, so if you have any questions about this control or our products, feel free to visit the SoftFluent forum.

Happy ribboning!

The R&D team.

Follow

Get every new post delivered to your Inbox.

Join 49 other followers