Quantcast
Channel: DevExpress Support Center (Examples)
Viewing all 7205 articles
Browse latest View live

How to bind SchedulerControl to an SQL Server database and customize Update/Delete/Insert queries without the use of the SqlCommandBuilder

$
0
0

This example illustrates how to setup SchedulerControl binding at runtime. Note that all appointment mappings and even SQL queries along with their parameters are adjusted in code without the use of the VS designer. This is the most flexible database-binding technique because it allows you to modify data-binding options and SQL queries with ease. For instance, we keep the time of modification along with the modified row by inserting a GETDATE function result into a TimeStamp column. Here are to corresponding SQL queries:

[SQL]
INSERT INTO CarScheduling (StartTime, EndTime, Subject, TimeStamp) VALUES (@StartTime, @EndTime, @Subject, GetDate()) UPDATE CarScheduling SET StartTime = @StartTime, EndTime = @EndTime, Subject = @Subject, TimeStamp = GetDate() WHERE ID = @ID DELETE FROM CarScheduling WHERE ID = @ID

 

To test this example locally, setup "SchedulerBindDynamically" sample database in your SQL Server instance. Utilize the SchedulerBindDynamically.sql file attached to this example to generate a sample database and table schema.

Note:
We do not use the SqlCommandBuilder Class capabilities to generate SQL queries as it is shown in the How to bind SchedulerControl to MS SQL Server database at runtime code example. The DbCommandBuilder.ConflictOption Property option of this class allows you to enable optimistic concurrency to prevent a concurrency violation error. Since we do not use this functionality, you might encounter this error when using this example. Fortunately, there are some ways that allows you to avoid this error. You can find them in the Introduction to Data Concurrency in ADO.NET MSDN article.

See Also:
Updating Data Sources with DataAdapters

Getting Started

Question Comments

Added By: Ian Zorrilla at: 2/3/2013 4:23:15 PM    

Do you have a sample project for this binding SchedulerControl to an SQL Server database?


Lesson 5 - Bind a Scheduler to MS SQL Database at Design Time

Lesson 7 - Create a Custom Appointment Edit Form

$
0
0
To learn more see the Getting Started article.
Question Comments

Added By: Stephan Y. at: 10/31/2016 2:29:55 AM    Hello,

in Lesson 7 is described how to create a custom Appointment Edit Form with the DevExpress.XtraScheduler.UI.AppointmentForm.

But I need to create a Appointment Edit Form with a "normal" devexpress form, just like you do it with this code example.
This code is a little bit more complex like the code in the lesson 7.
So have have a document with some remarks or explanations for this code?

BR
Stephan

Added By: Yulia (DevExpress Support) at: 10/31/2016 8:29:26 AM    

Hello Stephan,

The Custom Appointment Edit Form section of the Getting Started help topic describes how to create a custom Appointment Edit Form using the smart tag of the SchedulerControl. This form is a descendant of the DevExpress.XtraEditors.XtraForm class and implements the IDXManagerPopupMenu interface. The SchedulerControl generates code behind for this form automatically. Please note that this feature is available starting from v15.2.

If you are using older versions of our controls, you can use the approach described in the Custom form, custom fields and custom actions on reminder alert Code Example to create a custom Appointment Edit Form from scratch (inherit the form from the  DevExpress.XtraEditors.XtraForm class).

If you face any difficulties with the aforementioned approach, please create a separate ticket, describe the issue and provide a small sample that shows the problem. We will do our best to help you.

How to use DocumentIterator to export rich edit document in a custom document format

$
0
0

This example demonstrates how to export RichEditControl's document in a custom document format using a DocumentIterator object and a custom document visitor. The DocumentIterator is created to iterate through document elements. The custom document visitor is used to export document elements to a lightweight markup language (Markdown)/

The document visitor is implemented according to the Visitor pattern (by implementing the IDocumentVisitor interface). In this example, the custom document visitor is inherited from the DocumentVisitorBase class. The DocumentVisitorBase class implements the IDocumentVisitor interface by default. Thus, you can override only required methods of the DocumentVisitorBase class for custom document processing.

The document iterator moves over each document structure item and passes a custom document visitor object to the current item. The custom document visitor builds a string with lightweight markup for the currently processed document item.


See also: Traversing the Document

GridView - How to open popup on a hyperlink click

$
0
0

This example contains a Customers grid with a hyperlink column. When a hyperlink is clicked, a popup window is opened to display detail data - orders - of a given customer. Orders is the GridView extension in the content of the PopupControl.

See also:
How to display detail data within a popup window using ContentUrl (MVC)
How to display detail data within a popup window

Question Comments

Added By: Mayur Dhavle at: 9/10/2014 9:49:37 PM    

I have same functionality, but I have to pass multiple cell values to a controller action method. Can u please post a code snippet for same.

Added By: Larry (DevExpress Support) at: 9/10/2014 11:18:27 PM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T149660: GridView - How to pass multiple values when display detail data within a popup window. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

Added By: Islam Tosson at: 9/7/2015 5:53:03 AM    

Kindly, How can I replace the static text "Show Orders" in the line
...
hlSettings.Properties.Text = "Show Orders";
...
by a dynamic value in the current row [for example CustomerName value]

Best Wishes,

Added By: Helen (DevExpress Support) at: 9/7/2015 8:24:15 AM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T286685: How to display detail data within a popup window without static text . This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

Added By: Mark Davison 2 at: 7/18/2017 11:35:47 AM    Hi,
In the example, in the javascript you invoke the PerformCallback method on the detailGrid.

detailGrid.PerformCallback();
However, for me it shows reference error: detailGrid is not defined.

Difference between the example and my code is as follows-

In my case, on the Index page, based on some condition (of data in the model) I do an Html.RenderAction of one of two Master grid partial views. So I am unable to define the popupcontrol on the Index page itself because the model it uses is different from the model used on the Index page. (If I define the popup control on the Index page, it throws me exception that the model type is different).

How do I achieve this functionality? Please advise.

Thanks


Added By: Vova (DevExpress Support) at: 7/19/2017 12:14:20 AM    

Hello,

I've created a separate ticket on your behalf (T537187: GridView - How to show a detail GridView within PopupControl). It has been placed in our processing queue and will be answered shortly.

How to use a private font (a custom font distributed with the application) in XtraReport

$
0
0

This example demonstrates how to use a custom font distributed with the application in XtraReport.


The main idea of this approach is to use the PrivateFontCollection class to store custom font families. Use the Families property to access the FontFamily objects of your private fonts.

In this example, the static "FontCollection" property is used to store the report's private fonts. Then, in the report constructor, the private font families are used to specify fonts of the report controls.


This is a cross-platform approach, so it can be used for all technologies supported by XtraReports. However, there are some notes:


ASP.NET
The private font will be available only on your web server, so it won't be displayed in ASPxDocumentViewer by default if it is not installed on the client machine.

However, you can register this custom font on your webpage, for example by using the @font-face CSS rule. In this case, add this rule to your webpage with the viewer and set your ASPxDocumentViewer.SettingsReportViewer.UseIFrame property to the "false" value to prevent your report from being rendered in an iframe. This approach is demonstrated in this example.

WPF
The font cannot be registered globally by using the PrivateFontCollection in WPF, so the explicit reference to the embedded font is required there. The E5083: How to display a report that uses a private font (distributed with the application) in DocumentPreview code example demonstrates how to work around this limitation.

See also:
How to: Create a Private Font Collection (MSDN)

Question Comments

Added By: Katie Tobin at: 5/7/2018 12:20:50 PM    I'm trying to get this code to work for an XtraReport version 17.1 and there doesn't seem to be a customFontStyle property in the code behind of the xtra report file.  Am I missing something?  Have the steps changed to include a font with a report?

ASPxGridView - A simple Batch Editing implementation

$
0
0

This example illustrates a simple implementation of a new ASPxGridView Batch Editing Mode functionality available starting with version 13.2:
ASP.NET WebForms & MVC: GridView Batch Edit (What's new in 13.2)

This example is a standalone DB-independent solution of the online Batch Editing demo. Refer to the demo's Description for more information.

Handle the ASPxGridView RowInserting/RowUpdating/RowDeleting events if you want to submit a batch of modifications individually via a corresponding CRUD procedure.
Handle the ASPxGridView.BatchUpdate event if you want to submit a batch of modifications at once via a corresponding BatchUpdate procedure.

Note that this example uses a custom local data source stored in Session. The grid is bound to a list of objects of the GridDataItem type. The GridDataItem class here is implemented specially for this local data source. If you're using another data source, you can use the same approach to save the inserted/modified data in the RowInserting/RowUpdating/RowDeleting/BatchUpdate events without adding this class and modify your data by creating the corresponding requests to the data source in these event handlers

Question Comments

Added By: Chris Ferris at: 10/20/2016 6:23:10 AM    Is there an example which uses a dataset instead of a list?  This list method seems to have extra stuff like the public class GridDataItem, and defining column names and data types, that might not be necessary when the gridview is bound to a dataset?Added By: Mike (DevExpress Support) at: 10/21/2016 1:10:48 AM    

Hello,

I've created a separate ticket on your behalf (T441889: ASPxGridView - Simple Batch Edit with DataSet). It has been placed in our processing queue and will be answered shortly.

DXRichEdit for WPF: How to retain original image URI in HTML document

$
0
0

This example illustrates the use of a DevExpress.XtraRichEdit.Utils.RichEditImage.Uri property to retrieve original location of an image and store it in src attribute when a document is saved in HTML format.


ASPxDashboard - How to pass a hidden dashboard parameter to a custom SQL query

$
0
0

The following example shows how to override an initial or user-defined dashboard parameter value by changing it in the ASPxDashboard.CustomParameters event handler.
The dashboard in this example has a CustomerIdDashboardParameter parameter with a certain initial value. At runtime, its value is changed in the ASPxDashboard.SetInitialDashboardState event handler. This value is displayed in the Parameters dialog and can be changed by the end-user,
However, by handling the ASPxDashboard.CustomParameters event, we can validate the parameter value and ignore the value provided by the end-user.To accomplish this, the data is obtained using a custom SQL query with a parameter named CustomerIdParameter. The query parameter is bound to the CustomerIdDashboardParameter dashboard parameter. The value of this parameter is changed at runtime by handling the ASPxDashboard.CustomParameters event which is raised before the ASPxDashboard sends a query to a database. Thus, only the value passed in the ASPxDashboard.CustomParameters event is in effect.

How to color manually added shapes using the choropleth colorizer

$
0
0

This example demonstrates how to paint two triangles on a map using the choropleth colorizer.


Question Comments

Added By: Mario Kahn 1 at: 5/9/2018 8:18:09 AM    the new link to see the source code is not working

How to create appointments by dragging and dropping data from the Grid control

$
0
0
This example demonstrates how to to create a new appointment by dragging and dropping data from the data grid.
Question Comments

Added By: Piotr Wierzba at: 5/9/2018 8:57:46 AM    There is a bug in example.
I catch row with "Taylor Riley" and I go to schedluer but do not drop it to scheduler.
After that when I want to drag and drop other row, I see on scheduler prievious row ("Taylor Riley") - till I drop it on scheduler.

ASPxGridView - Batch Edit - Cancel editor/row editing in the client FocusedCellChanging event

$
0
0
Starting from version 17.1 we have introduced a new client-side FocusedCellChanging event. This event allows you to skip focusing and editing a cell.
This example demonstrates different ways to skip or prevent editing certain cells.
The main idea is to get the currently focused cell using the ASPxClientGridViewFocusedCellChangingEventArgs.cellInfo property and decide whether it is required to skip focusing or not:
[JavaScript]
function onFocusedCellChanging(s, e){if(e.cellInfo.column.name == 'command') e.cancel = true;elseif(e.cellInfo.column.fieldName == 'SupplierID') e.cancel = true;elseif(e.cellInfo.column.fieldName == 'UnitsInStock'&& (e.cellInfo.rowVisibleIndex < 3 || e.cellInfo.rowVisibleIndex > 7)) e.cancel = true;elseif(e.cellInfo.column.fieldName == 'UnitPrice'&& s.batchEditApi.GetCellValue(e.cellInfo.rowVisibleIndex, 'UnitPrice')> 22) e.cancel = true;}

Note: the FocusedCellChanging event can't prevent editor focusing if the ASPxGridView.SettingsEditing -> BatchEditSettings -> EditMode property is set to Row.

How to create a master-detail grid

$
0
0

In the 12.1 version we implemented a Master-Detail feature, and now we provide it out of the box. We have added a new solution, which shows how to use our new approach.


With later versions of our controls you can use the previous workaround:

To accomplish this, it is necessary to use one GridControl as a template for a data row of another GridControl.

Limitations of the previous approach:

Vertical scrolling is performed per master row. For an example on how to implement vertical scrolling of details, please see 'Persistent Row State' in the DXGrid's demo.

Question Comments

Added By: Raphi Levine 1 at: 5/10/2018 8:55:32 AM    Do you have a Winforms sample for this as well or just WPF?

Getting Started - Creating an ASP.NET MVC Dashboard Designer Application (Runtime sample)

How to represent an enumeration property via a drop-down box with check boxes

$
0
0

Scenario:

There is an enumeration type decorated with the FlagsAttribute, which means that an enumeration can be treated as a set of flags. There is also a property of this enumeration type inside the business class. This is helpful when several predefined enumeration values can be stored using this data property. In the UI, this data property is usually represented via an editor with multiple check boxes:


Steps To Implement:

Since there is no standard  PropertyEditor for enumerations that would allow you to store several values at once, it is common to implement custom Property Editors for this task. A custom PropertyEditor will take data property value as its input and represent it in the UI using a custom visual control. There will be one PropertyEditor for WinForms (based on the CheckedComboBoxEdit control from the XtraEditors Suite) and one for ASP.NET (based on the ASPxGridLookup control from our ASPxGridView and Editors Suite), because there is no platform-agnostic way to achieve such a look and feel.


Consider following the steps below to implement and use editors from this example in your project.
1. Implement an enumeration type decorated with the FlagsAttribute as shown in the E689.Module\BusinessObjects\DemoObjects.xx file;
2. Copy the E689.Module.Win\Editors\EnumPropertyEditorEx.xx file into YourSolutionName.Module.Win project;
3. Copy the E689.Module.Web\Editors\ASPxEnumPropertyEditorEx.xx file into YourSolutionName.Module.Web project;
4. Build the solution and invoke the Model Editor for the ModelDesignedDiffs.xafml files from YourSolutionName.Module.Win and YourSolutionName.Module.Web projects.

5. Locate the BOModel | YourClassName | Members | YourEnumerationProperty node and set its PropertyEditorType property to the corresponding EnumPropertyEditorEx types.

 

See Also:

Implement Custom Property Editors
How to represent a enumeration property via radio buttons or check boxes on the Web

Question Comments

Added By: Pawel Botwina at: 7/6/2013 1:11:36 AM    

Hello,

How can I filter by flags enum property in the server mode? I mean filtering the ListView by AutoFilterRow.

Added By: Alex Kads at: 4/4/2014 2:35:40 PM    

would that same code for WEB

Added By: Dennis (DevExpress Support) at: 4/8/2014 12:45:41 AM    

@Alex: While we do not have a ready Web version of this example, you may find the code from the E1807 example helpful. Thanks.

Added By: Anatol (DevExpress Support) at: 4/9/2014 9:32:02 AM    

Web version is added.

Added By: Leong Vai Long at: 5/14/2014 3:22:04 AM    

Hi, I had try this method for the XAF web version. The question is how i want to use the XAF Display Name to show in the lookup? bcos I only see the enum values.
Thanks.

Added By: Dennis (DevExpress Support) at: 5/14/2014 9:09:47 AM    

@Leong: This particular functionality is not implemented in this example solution. You would need to modify the E689.Module.Web.Editors.EnumPropertyEditorEx class to achieve this. While we do not have a ready sample, feel free to contact our ASP.NET team on how to implement your task with the ASPxGridLookup component used in this example. Once you receive a solution for this component, it can be easily integrated in XAF.

Added By: Leong Vai Long at: 5/14/2014 10:46:46 PM    

Hi Dennis,

1. Is it possible to change the ASPXGridLookup with the ASPXDropDownEdit? This is the link http://blog.zerosharp.com/three-ways-to-store-a-list-of-currency-codes-in-xaf/#disqus_thread, but this example use the string, how to convert it to enum?
2. How to contact your ASP.NET team to implement my task with the ASPXGridLookup?

Thanks.

Added By: Dennis (DevExpress Support) at: 5/15/2014 7:07:00 AM    

@Leong:

A1: Sure, you are free to implement your own custom PropertyEditor based on any control you want.
A2: You can submit a new question through https://www.devexpress.com/Support/Center/Question/Create and specify the ASP.NET Web Forms platform and ASPxGridView and Editors Suite as a product. In the new ticket describe what you have implemented so far, attach a small non-XAF sample where you tried to customize the ASPxDropDownEdit control and also describe your requirements in detail. Before doing this, you may want to check out the documentation on our ASP.NET Web Forms controls and also corresponding demos. To effectively search our knowledge base, documentation and examples, you may find our Search Engine helpful.

 

Added By: Dennis (DevExpress Support) at: 5/19/2014 6:56:03 AM    

@Leong:

I have modified the Web version of this custom editor to support localized values. Please refer to the attachment.

Added By: MohammedFarooq at: 5/16/2016 7:28:54 AM    Hi Dennis,

How can i read the Text value that is displayed in the editor? Added By: Dennis (DevExpress Support) at: 5/16/2016 7:56:25 AM    

@MohammedFarooq: There are different properties like EditValue/Text/Value in underlying WinForms and ASP.NET controls. Would you please elaborate a bit more on how you are going to reuse these display values (please submit a separate ticket via the https://www.devexpress.com/Support/Center/Question/Create service for that purpose)?

Added By: Tony Tadros Zaky at: 6/10/2016 11:46:04 AM    Hello Devexpress,

trying to use your example but i am having an issue

if the combobox opened and closed without changing the value the save object is marked as changed

is there is a way to avoid the extra warning specially the user did not change the value

Regards
Tony Added By: Dennis (DevExpress Support) at: 6/13/2016 1:58:28 AM    

@Tony: I've created a separate ticket on your behalf (T391277: E689 - How to avoid the save confirmation when opening a drop down without changing its value). It has been placed in our processing queue and will be answered as soon as we can.

Added By: Lucian Zavate at: 8/22/2016 12:33:54 PM    Hi Dennis,

Is it possible to change GridLookupSelectionMode dynamicaly? I would like to have this control behave differently based on another property editor value. In other words I would like to have a radio button by default (got this by changing GridLookupSelectionMode in AspxEnumPropertyEditorEx.cs) and based on the value selected on another property to switch from radio buttons to check boxes (set GridLookupSelectionMode to multiple).

Regards,
Lucian Added By: Alexey (DevExpress Support) at: 8/22/2016 10:00:05 PM    

Hello Lucian,

I've created a separate ticket on your behalf (T417979: Switch from radio buttons to check boxes base on the object's value). It has been placed in our processing queue and will be answered shortly.

Added By: Lucian Zavate at: 8/22/2016 10:34:24 PM    Hi Dennis,

Thanks. I will be watching that thread.

Regards,
Lucian Added By: Alexey (DevExpress Support) at: 8/22/2016 11:04:26 PM    You're welcome.Added By: Elaya K at: 5/13/2018 9:15:02 PM        Can u help me in that,how to add data in checked combo box without using enum.Because If I use enum I can able to add only the static text but I need to load data from class objects.

How to save CheckState for TreeListNode in a bound mode

$
0
0

This example demonstrates how to save TreeListNode.CheckState in a bound mode. It is necessary to create an instance of the SaveCheckHelper class and pass TreeList and a field, containing CheckState, to a datasource bound to TreeList.

In recent versions of our components, use the TreeList.CheckBoxFieldName property to bind built-in checkboxes to a field in the data source.

How to replace standard DXRichEdit command with your own custom command

$
0
0
This example illustrates the technique used to modify the functionality of existing DXRichEdit commands.
The RichEditControl exposes the IRichEditCommandFactoryService interface that enables you to substitute default command with your own custom command.
First, create a command class, inherited from the command that you've decided to replace. Override its methods. The main functionality and command specifics is located in the Execute or the ExecuteCore method (the latter does not check for the command availability).
Then, create a class implementing the IRichEditCommandFactoryService. You should override the CreateCommand method to create an instance of a custom command class if an identifier of a certain command is passed as a parameter. So, instead of the default command, a custom command will be used by the RichEditControl.
Finally we use this class to substitute the default RichEditControl's service.

How to customize a GridControl refreshing bar

$
0
0

This example demonstrates how to customize a color of the GridControl's refreshing bar (shown on Android) and refreshing icon (shown on iOS). A complete description is available in the How to: Customize Refresh Indicators topic.

How to delete all criteria corresponding to a particular field from CriteriaOperator

$
0
0

This example demonstrates how to implement a helper that removes all expressions referencing a certain property from the CriteriaOperator. For example, you may want to programmatically remove fragments like "[SavedPassword] = '***'" from filter expressions that persist on client computers, because you decided to remove the SavedPassword property from the model for security reasons.

Although this task can be accomplished using regular expressions, this approach is too complicated and is applicable only to CriteriaOperator expressions that follow a certain pattern. This example uses a different technique, which allows you to support expressions of any complexity with minimum effort.

The solution demonstrated in this example uses the concept described in this Knowledge Base article: Implementation of the base class for a CriteriaOperator expression patcher. The DevExpress.Data.Filtering.Helpers.ClientCriteriaLazyPatcherBase.AggragatesCommonProcessingBase class is used in this example as a base class for the CriteriaPatcherSkipProperties class (in version 17.2 and earlier use the CriteriaPatcherBase class implemented in the example).

To remove any reference to a specific property from the CriteriaOperator expression, override the CriteriaPatcherBase.VisitProperty method, and return null (Nothing in Visual Basic) if the property name matches the name of a property that should be removed.

[C#]
protectedoverrideCriteriaOperatorVisitProperty(OperandPropertytheOperand){if(PropertiesToremove.Contains(theOperand.PropertyName))returnnull;returntheOperand;}
[VB.NET]
ProtectedOverridesFunction VisitProperty(ByVal theOperand As OperandProperty) As CriteriaOperatorIf PropertiesToremove.Contains(theOperand.PropertyName) ThenReturnNothingEndIfReturn theOperandEndFunction

However, this is incomplete. The expression will contain invalid statements if you simply remove properties from it: "() = #2015-12-30# And StartsWith([City], 'q')". To delete invalid statements from the expression, override the VisitAggregate, VisitFunction, VisitGroup, VisitIn, VisitUnary, VisitBinary, and VisitBetween methods. The implementation of overridden methods is demonstrated in the CriteriaPatcherSkipProperties.cs and CriteriaPatcherSkipProperties.vb files.

See also:
Implementation of the base class for a CriteriaOperator expression patcher

How to create a custom converter to convert the CriteriaOperator to the System.String type

How to generate a sequential number for a persistent object within a database transaction (XAF)

$
0
0

This example illustrates one of the possible approaches to implementing an identifier field with sequential values. Alternate approaches are listed in the An overview of approaches to implementing a user-friendly sequential number for use with an XPO business class KB article.

Scenario

This is a variation of the How to generate and assign a sequential number for a business object within a database transaction, while being a part of a successful saving process XPO example, which was specially adapted for XAF applications.

In particular, for better reusability and more smooth integration with the standard XAF CRUD Controllers, all the required operations to generate sequences are managed within the base persistent class automatically when a persistent object is being saved. For more developer convenience, this solution is organized as a reusable XAF module - GenerateUserFriendlyId.Module. This module consists of several key parts:

    - Sequence and SequenceGenerator are auxiliary classes that take the main part in generating user-friendly identifiers. Take special note that the SequenceGenerator.Initialize method must be called during your XAF application startup for the correct operation.

    - UserFriendlyIdPersistentObject is a base persistent class that subscribes to XPO's Session events and delegates calls to the core classes above. Normally, you must inherit your own business classes from this base class to get the described functionality in your project.

    - IUserFriendlyIdDomainComponent is a base domain component that should be implemented by all domain components that require the described functionality.

Check the original example description first for more information on the demonstrated scenarios and functionality.




Steps to implement
1. Copy and include the GenerateUserFriendlyId.Module project into your solution and make sure it is built successfully.  Invoke the Module or Application Designer for the YourSolutionName.Module/Module.xx  or YourSolutionName.Wxx/WxxApplication.xx files by double-clicking it in Solution Explorer. Invoke the Toolbox (Alt+X+T) and then drag & drop the GenerateUserFriendlyIdModule component into the modules list on the left.

2. For apps with no security or with the Client-Side Security (XPObjectSpaceProvider or SecuredObjectSpaceProvider):
In the YourSolutionName.Wxx/WxxApplication.xx files, modify the CreateDefaultObjectSpaceProvider method to call the SequenceGenerator.Initialize method as shown in the Demo.Wxx\WxxApplication.xx files:

[C#]
protectedoverridevoidCreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventArgsargs){IXpoDataStoreProviderdataStoreProvider=XPObjectSpaceProvider.GetDataStoreProvider(args.ConnectionString,args.Connection,true);// Web:// IXpoDataStoreProvider dataStoreProvider = GetDataStoreProvider(args.ConnectionString, args.Connection);GenerateUserFriendlyId.Module.SequenceGenerator.Initialize(dataStoreProvider);...}

For apps with the Middle Tier Security (DataServerObjectSpaceProvider):
In the YourSolutionName.ApplicationServer project, locate and modify the serverApplication_CreateCustomObjectSpaceProvider or CreateDefaultObjectSpaceProvider  methods to call the SequenceGenerator.Initialize method in the same manner.


3.
 If you are using pure XPO classes, then inherit your required business classes from the module's UserFriendlyIdPersistentObject one and use the derived SequenceNumber property as required:

[C#]
publicclassContact:GenerateUserFriendlyId.Module.BusinessObjects.UserFriendlyIdPersistentObject{[PersistentAlias("concat('C', ToStr(SequentialNumber))")]publicstringContactId{get{returnConvert.ToString(EvaluateAlias("ContactId"));}}

If you are using DC interfaces, then implement the IUserFriendlyIdDomainComponent interface by your custom domain component:

[C#]
publicinterfaceIDocument:GenerateUserFriendlyId.Module.BusinessObjects.IUserFriendlyIdDomainComponent{[Calculated("concat('D', ToStr(SequentialNumber))")]stringDocumentId{get;}

Additionally for DC, use the UserFriendlyIdPersistentObject as a base class during your custom domain component registration, e.g.:

[C#]
XafTypesInfo.Instance.RegisterEntity("Document",typeof(IDocument),typeof(GenerateUserFriendlyId.Module.BusinessObjects.UserFriendlyIdPersistentObject));

Note that the sequential number functionality shown in this example does not work with DC shared parts , because it requires a custom base class, which is not allowed for shared parts.

4. For more information, download and review the Address, Contact, and IDocument types within the Demo.Module project. These are test business objects that demonstrate the use of the described functionality for XPO and DC respectively. A required format for the user-friendly identifier property in these end classes is defined within an aliased property (ContactId in the example above) by concatenation of a required constant or dynamic value with the SequentialNumber property provided by the base UserFriendlyIdPersistentObject class. So, if you need to have a different format, modify the PersistentAliasAttribute expression as your business needs dictate.

 

IMPORTANT NOTES

1. As an alternative, you can implement much simpler solutions at the database level or by using the built-in DistributedIdGeneratorHelper.Generate method. Refer to the An overview of approaches to implementing a user-friendly sequential number for use with an XPO business class article for more details.

2.  In the Integrated Mode and middle-tier Application Server scenario the newly generated sequence number will appear in the DetailView only after a manual refresh (i.e., it will be empty right away after saving a new record), because the sequence is generated on the server side only and is not passed to the client. You can download a ready test project for these configurations here. See also the "Refresh the Identifier field value in UI" section in this KB article.
3. You can specify or seed the initial sequence value manually: either by editing the Sequence table in the database or using the standard XPO/XAF means by manipulating the Sequence objects, e.g.:

[C#]
using(IObjectSpaceos=Application.CreateObjectSpace(typeof(Sequence))){Sequencesequence=os.FindObject<Sequence>(CriteriaOperator.Parse("TypeName=?",typeof(E2829).FullName));sequence.NextSequence= 5;os.CommitChanges();}

See also:
How to create multiple sequences based on the a class property value, not one sequence per class type


Your feedback is needed!
We would greatly appreciate it if you share your feedback here in comments or rather participate in this short survey (~3 min).

Question Comments

Added By: Mr. Murat YILMAZ at: 10/7/2012 9:15:18 AM    

Thanks for the example. I developed ISequentialNumber domain component which based on this article and code. Now this sequential number functonatility shon in this example work with domain components and shared parts.

using System;
using System.Collections.Generic;
using System.ComponentModel;

using DevExpress.ExpressApp.DC;
using DevExpress.Persistent.Base;
using DevExpress.Xpo;
using DevExpress.Xpo.Metadata;
using DevExpress.ExpressApp;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;

using MyWay.Xaf.Module;
using MyWay.Xaf.Utils.Sequence;

namespace MyWay.Xaf.Module
{
    [DomainComponent]
    [NavigationItem]
    public interface ISequentialNumber
    {
        #region PROPERTIES

        #region SequentialNo

        [Persistent]
        string SequentialNo
        {
            get;
        }

        #endregion SequentialNo

        #region SequentialNumber
        
        [System.ComponentModel.Browsable(false)]
        [Indexed(Unique = false)]
        long SequentialNumber
        {
            get ;
            set;
        }

        #endregion SequentialNumber

        #endregion PROPERTIES
    }

    [DomainLogic(typeof(ISequentialNumber))]
    public class ISequentialNumberLogic
    {

            public static string Get_SequentialNo(ISequentialNumber instance)
            {
                return "asd" + instance.SequentialNumber.ToString();
            }

            

        private static object syncRoot = new object();
        private static SequenceGenerator sequenceGenerator;

        #region METHODS

        #region PUBLIC METHODS

        #region GenerateSequence

        public static void GenerateSequence(ISequentialNumber instance)
        {
            lock (syncRoot)
            {
                Dictionary<string, bool> typeToExistsMap = new Dictionary<string, bool>();

                foreach (object item in ((XPBaseObject)instance).Session.GetObjectsToSave())
                {
                    typeToExistsMap[((XPBaseObject)instance).Session.GetClassInfo(item).FullName] = true;
                }

                if (sequenceGenerator == null)
                {
                    sequenceGenerator = new SequenceGenerator(typeToExistsMap);
                }

                SubscribeToEvents(((XPBaseObject)instance).Session);
                OnSequenceGenerated(sequenceGenerator.GetNextSequence(((XPBaseObject)instance).ClassInfo), instance);
            }
        }

        #endregion GenerateSequence

        #endregion PUBLIC METHODS

        #region PROTECTED METHODS

        #region OnSaving

        public static void OnSaving(ISequentialNumber instance)
        {
            try
            {
                //base.OnSaving();
                if (((XPBaseObject)instance).Session.IsNewObject(instance) && !typeof(NestedUnitOfWork).IsInstanceOfType(((XPBaseObject)instance).Session))
                {
                    GenerateSequence(instance);
                }
            }
            catch
            {
                CancelSequence(((XPBaseObject)instance).Session);
                throw;
            }
        }

        #endregion OnSaving

        #endregion PROTECTED METHODS

        #region INTERNAL METHODS

        #endregion INTERNAL METHODS

        #region PRIVATE METHODS

        #region AcceptSequence

        private static void AcceptSequence(Session session)
        {
            lock (syncRoot)
            {
                if (sequenceGenerator != null)
                {
                    try
                    {
                        sequenceGenerator.Accept();
                    }
                    finally
                    {
                        CancelSequence(session);
                    }
                }
            }
        }

        #endregion AcceptSequence

        #region CancelSequence

        private static void CancelSequence(Session session)
        {
            lock (syncRoot)
            {
                UnSubscribeFromEvents(session);
                if (sequenceGenerator != null)
                {
                    sequenceGenerator.Close();
                    sequenceGenerator = null;
                }
            }
        }

        #endregion CancelSequence

        #region Session_AfterCommitTransaction

        private static void Session_AfterCommitTransaction(object sender, SessionManipulationEventArgs e)
        {
            
            AcceptSequence(e.Session);
        }

        #endregion Session_AfterCommitTransaction

        #region Session_AfterRollBack

        private static void Session_AfterRollBack(object sender, SessionManipulationEventArgs e)
        {
            CancelSequence(e.Session);
        }

        #endregion Session_AfterRollBack

        #region Session_FailedCommitTransaction

        private static void Session_FailedCommitTransaction(object sender, SessionOperationFailEventArgs e)
        {
            CancelSequence((Session)sender);
        }

        #endregion Session_FailedCommitTransaction

        #region SubscribeToEvents

        private static void SubscribeToEvents(Session session)
        {
            if (!(session is NestedUnitOfWork))
            {
                session.AfterCommitTransaction += Session_AfterCommitTransaction;
                session.AfterRollbackTransaction += Session_AfterRollBack;
                session.FailedCommitTransaction += Session_FailedCommitTransaction;
            }
        }

        #endregion SubscribeToEvents

        #region UnSubscribeFromEvents

        private static void UnSubscribeFromEvents(Session session)
        {
            if (!(session is NestedUnitOfWork))
            {
                session.AfterCommitTransaction -= Session_AfterCommitTransaction;
                session.AfterRollbackTransaction -= Session_AfterRollBack;
                session.FailedCommitTransaction -= Session_FailedCommitTransaction;
            }
        }

        #endregion UnSubscribeFromEvents

        #region OnSequenceGenerated

        private static void OnSequenceGenerated(long newId, ISequentialNumber instance)
        {
            instance.SequentialNumber = newId;
        }

        #endregion OnSequenceGenerated

        #endregion PRIVATE METHODS

        #endregion METHODS
    }
}

Added By: Luis Alberto Santiago at: 2/25/2013 8:06:36 PM    

Hi Mr. Murat YILMAZ, Can yo provide some example to use the class. I am looking it for shared parts

Added By: Andrew Bingham 2 at: 7/8/2013 3:38:51 AM    

I implemented this OK in a Solution

When I eimplmented it in a different solution I got an Exception
"Message: Value cannot be null.
Parameter name: Application"

thrown at:

    public static void Initialize() {
            Guard.ArgumentNotNull(Application, "Application");

Added By: Dennis (DevExpress Support) at: 7/11/2013 3:11:06 AM    

@Andrew: You forgot to add the following code:

public override void Setup(XafApplication application) {
            base.Setup(application);
            SequenceGeneratorInitializer.Register(application);
        }

You will not experience this and similar difficulties if you simply add the reusable module into your solution as per instructions above.

Added By: Carlitos at: 8/23/2014 6:46:05 PM    

Hi,
Is this now supported in Middle-Tier XAF applications?

Thanks,

Carlitos

Added By: Dennis (DevExpress Support) at: 8/25/2014 4:38:12 AM    

We have not performed additional R&D and testing of this particular example in a middle-tier scenario. Moreover, I see technical problems using this particular solution in this configuration, because here we use ExplicitUnitOfWork, which implies that it will be a sole owner of the database connection. Probably, for this configuration, it is better to stick to a standard solution, e.g. using database triggers. 

Added By: Carlitos at: 8/25/2014 9:34:23 AM    

Hi Dennis,
But how does the Middle-tier handle database connections? I thought it would do some sort of connection pooling and manage all client connections?

Why do you think that Triggers are a good alternative?

Carlos

Added By: Dennis (DevExpress Support) at: 8/26/2014 6:14:27 AM    

By default, the middle-tier app server uses ThreadSafeDataLayer to effectively handle requests from multiple clients at the same time. Connection pooling may be used here, but this is not managed by us by default and is rather controller by ADO.NET transparently for a consumer. My main concern here was that in such a multi-user environment it will not be possible to exclusively lock the connection by one user.
A solution at the database level looks more universal as it works at the database level and is irrelevant to whether the app server is used or not. 

Added By: Vishwas Mokashi at: 4/14/2015 11:21:58 AM    

In XAF application I have about 25 various business objects that need to generate unique user friendly sequence numbers in when saved. For example Customer Number, Invoice Number, Order Number, etc. Many users are going to work concurrently and everything should work in transaction.

Which approach should I use, the one in E2620 or E2829?.

I felt E2620 a bit better as I need not to inherit my classes (25 of them) from  UserFriendlyIdPersistentObject as shown in E2829.  

But approach in E2829 is said to be primarily for XAF applications

Added By: Dennis (DevExpress Support) at: 4/15/2015 4:47:25 AM    

@Vishwas: Both E2620  and E2829 demonstrate the same solution using ExplicitUnitOfWork. E2829 is just a bit better integrated with the XAF infrastructure.
If you do not want to inherit from a common base class, I suggest you consider using How to generate a sequential and user-friendly identifier field within a business class, which is simpler to implement and provides similar capabilities without using ExplicitUnitOfWork.

Added By: Vishwas Mokashi at: 4/17/2015 6:54:45 AM    

OK thanks Dennis.

Will simpler approach in "How to generate a sequential and user-friendly identifier field within a business class" handle concurrent users creating same business objects properly?. We can assume about 25 Concurrent users for same business object, with SQL Server DB.

Some users will be accessing system over low banddwidth VPN internet connection. (for Sale Invoice object which needs to generate sequencial Invoice Numbers)

Added By: Dennis (DevExpress Support) at: 4/20/2015 7:58:16 AM    

@Vishwas: Yes, it will. The DistributedIdGeneratorHelper class tries to save a record and repeats its attempts several times until it reaches the maximum number or saves data completely. Check out the corresponding source code for more details on how this works.

    public static class DistributedIdGeneratorHelper {
        public const int MaxIdGenerationAttemptsCounter = 7;
        public static int Generate(IDataLayer idGeneratorDataLayer, string seqType, string serverPrefix) {
            for(int attempt = 1; ; ++attempt) {
                try {
                    using(Session generatorSession = new Session(idGeneratorDataLayer)) {
                        CriteriaOperator serverPrefixCriteria;
                        if(serverPrefix == null) {
                            serverPrefixCriteria = new NullOperator("Prefix");
                        }
                        else {
                            serverPrefixCriteria = new BinaryOperator("Prefix", serverPrefix);
                        }
                        OidGenerator generator = generatorSession.FindObject<OidGenerator>(
                            new GroupOperator(new BinaryOperator("Type", seqType), serverPrefixCriteria));
                        if(generator == null) {
                            generator = new OidGenerator(generatorSession);
                            generator.Type = seqType;
                            generator.Prefix = serverPrefix;
                        }
                        generator.Oid++;
                        generator.Save();
                        return generator.Oid;
                    }
                }
                catch(LockingException) {
                    if(attempt >= MaxIdGenerationAttemptsCounter)
                        throw;
                }
            }
        }Added By: Vishwas Mokashi at: 4/21/2015 6:03:28 AM    

Thanks Dennis

Added By: Konstantin B (DevExpress) at: 12/4/2017 1:20:01 AM    Update: This example illustrates one of the possible approaches to implementing an identifier field with sequential values. Alternate approaches are listed in the An overview of approaches to implementing a user-friendly sequential number for use with an XPO business class KB article.Added By: Cecil Carter at: 3/3/2018 7:30:11 AM    I've tried running the example scenario against a MySQL database and I'm receiving the following error. I assume this is related to the SQL statement generated by the ORM for MySQL. Is there a possible work around to this error?

DevExpress.ExpressApp.Updating.CompatibilityException
  HResult=0x80131509
  Message=Unable to create 'PrimaryKey' 'PK_Sequence'. Parent: 'Sequence'. Error: Executing Sql 'alter table `Sequence` add constraint `PK_Sequence` primary key (`TypeName`)' with parameters '' exception 'MySql.Data.MySqlClient.MySqlException (0x80004005): BLOB/TEXT column 'TypeName' used in key specification without a key length
   at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
   at DevExpress.Xpo.Logger.LogManager.Log[T](String category, LogHandler`1 handler, MessageHandler`1 createMessageHandler)
   at DevExpress.Xpo.DB.ConnectionProviderSql.ExecSql(Query query)'
  Source=DevExpress.ExpressApp.v17.2
  StackTrace:
   at DevExpress.ExpressApp.Updating.DatabaseUpdater.Update()
   at GenerateUserFriendlyId.Win.GenerateUserFriendlyIdWindowsFormsApplication.GenerateUserFriendlyIdWindowsFormsApplication_DatabaseVersionMismatch(Object sender, DatabaseVersionMismatchEventArgs e) in C:\Users\Cecil Carter\Downloads\eXpressApp Framework\17.2.5\E2829\Demo.Win\WinApplication.cs:line 26
   at DevExpress.ExpressApp.XafApplication.OnDatabaseVersionMismatch(DatabaseVersionMismatchEventArgs args)
   at DevExpress.ExpressApp.XafApplication.CheckCompatibilityCore()
   at DevExpress.ExpressApp.XafApplication.CheckCompatibility()
   at DevExpress.ExpressApp.XafApplication.Logon(PopupWindowShowActionExecuteEventArgs logonWindowArgs)
Inner Exception 1:
UnableToCreateDBObjectException: Unable to create 'PrimaryKey' 'PK_Sequence'. Parent: 'Sequence'. Error: Executing Sql 'alter table `Sequence` add constraint `PK_Sequence` primary key (`TypeName`)' with parameters '' exception 'MySql.Data.MySqlClient.MySqlException (0x80004005): BLOB/TEXT column 'TypeName' used in key specification without a key length
   at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
   at DevExpress.Xpo.Logger.LogManager.Log[T](String category, LogHandler`1 handler, MessageHandler`1 createMessageHandler)
   at DevExpress.Xpo.DB.ConnectionProviderSql.ExecSql(Query query)'
Inner Exception 2:
SqlExecutionErrorException: Executing Sql 'alter table `Sequence` add constraint `PK_Sequence` primary key (`TypeName`)' with parameters '' exception 'MySql.Data.MySqlClient.MySqlException (0x80004005): BLOB/TEXT column 'TypeName' used in key specification without a key length
   at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
   at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
   at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
   at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
   at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery()
   at DevExpress.Xpo.Logger.LogManager.Log[T](String category, LogHandler`1 handler, MessageHandler`1 createMessageHandler)
   at DevExpress.Xpo.DB.ConnectionProviderSql.ExecSql(Query query)'
Inner Exception 3:
MySqlException: BLOB/TEXT column 'TypeName' used in key specification without a key length

Added By: Dennis (DevExpress Support) at: 3/5/2018 12:35:24 AM    

@Cecil Carter: I've created a separate ticket on your behalf (T612198: MySql - The "BLOB/TEXT column 'XXX' used in key specification without a key length" error may occur when using a string key property). It has been placed in our processing queue and will be answered shortly.

Viewing all 7205 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>