In this article, we’ll see how to use multiple stores in your CodeFluent Entities application. In a previous post, we explained that the Modeler doesn’t provide a “Store Name” property in the producer’s configuration property grid. It’s now fully supported in the product so you don’t need to modify your XML parts by hand.
However, before we go any further, let’s bring some theory. The CodeFluent Entities “store” concept can be seen as a virtual storage unit and is mainly used by the persistence layer producers. Your CodeFluent Entities model contains by default one store which is always visible in your model, in the Visual Studio’s solution explorer tree view:
If you need to add a new Store, right-click on the “Stores” node and select “Add new Store”. Simply choose a name and your application now contains two stores: CarRental and CarRentalReferential.
Okay, great… but why would I want to do this?
When you develop an application, you may feel the need to dispatch your tables (inferred from model entities) in more than one database. For example, I want to create the Customer table in the CRM Database, and the Product table in the Master Data Database. Well, this is exactly why the store concept exists. Another example is shown here in this diagram:
Now, how to configure the “City”, “Address” and “Country” entities so their inferred tables will be generated to the CarRental database? It’s very easy : just select each of them, open the Properties window (F4), select the property grid Advanced tab (pointed by the red arrow below), and specify the target store like this:
Then you can define two persistence producers in your project and assign each of them a specific store:
Now don’t forget to configure your store and set it a specific connectionString. By building your model, CodeFluent Entities will generate the code corresponding to each store. The right things in the right places 😉 !
To conclude, I’d like to point out that, by design and by default, you can’t create model-level relationships between entities from different stores. Databases could be located in different servers or in different storage systems. But if you know what you’re doing, and still need this, you can change this default behavior by setting the allowCrossStoreRelations attribute on your project.
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.
<cfe:BoolControl ID="BoolControl1" runat="server" Value='<%# Bind("IsCustomer") %>' TrueText="Yes" FalseText="No" UnspecifiedText="Undefined" BoolControlType="HorizontalRadioButtonList" />
<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:
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.
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.)
<Grid> <DataGrid x:Name="MyDataGrid" /> </Grid>
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
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:
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 R&D team.
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:
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);
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 :
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.
The R&D team.