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

How to replace the cursor with a thumbnail image while dragging a card in the LayoutView

$
0
0

This example demonstrates how to replace the standard cursor with a miniature copy of the dragged card during the drag-and-drop operation in the LayoutView.

Question Comments

Added By: Simon Hewitt at: 10/20/2015 5:55:43 AM    

This just crashes each time I run it. (in cardPainter.DrawObject)

Added By: Andrew Ser (DevExpress Support) at: 10/20/2015 7:21:32 AM    Hello Simon,
Thank you for letting us know. We will research why the NullReferenceException is thrown and modify the example soon.Added By: Gosha (DevExpress Support) at: 10/21/2015 3:05:57 AM    

Thank you for your patience, Simon. Starting with version 14.1.7, it's necessary to pass a card to the LayoutView.DrawCard property to get it work. This property is private. So, you need to use Reflection to get it.


How to add custom properties to a DetailView dynamically at runtime

$
0
0

Suppose that it is necessary to provide a capability to work with documents. These documents can have various sets of fields, in various orders. To implement this scenario using standard XAF tools, it is necessary to create a lot of business classes, one for each kind of document. This solution doesn't allow the creation of a new document kind.


This example solves the described above task in the following way:


There is a Document class, which contains fields, common for all documents. It has an associated collection of document items, represented by the DocumentItemBase class and its descendants. To place document items into the Document DetailView, a custom property editor named DocumentItemsPropertyEditor is implemented. It is used for the Document.Items collection and draws a table with editors associated with document items. As a result, it is possible to customize editors shown in the DetailView at runtime.


Note that the example uses the InMemoryDataStoreProvider. To use another database, you need to modify the Session_Start event handler from the Global.asax.cs file.

See Also:
Implement Custom Property Editors
How do I provide the capability to create a new business class at runtime and allow end-users to define its structure via the application UI?

Question Comments

Added By: vguruv at: 7/5/2012 6:56:25 AM    

Does not work in edit mode on v12.1.4

Added By: Louis Z at: 5/26/2014 7:12:10 AM    

This example fails on 'New'.    Run, click new button.

NullReferenceExeption:  Object reference not set to an instance of an object.

private void CreateLayoutItems(LayoutControl layout) {
....
           for (int i = 0; i < itemsPerRow - columnIndex; i++) {
FAIL  -->              row.Add(new EmptySpaceItem());
           }

Added By: Anatol (DevExpress Support) at: 5/26/2014 10:23:37 AM    I have fixed the problem. Please see the updated example.

TileNavPane - How to change the arrow glyph

$
0
0
This example illustrates how to change TileNavPane's arrow (separator) glyph

RibbonForm - How to override caption painter and draw caption area manually

$
0
0
This example illustrates how to override RibbonForm's caption painter in order to draw the caption manually

How to integrate the Web Report Designer into a web application

$
0
0

This example demonstrates how you can integrate the Web Report Designer into your web application. The application contains a simple report catalog, allowing you to add, delete, and edit reports whose layout data is stored in a custom data storage (i.e., an MDB database).

 Additionally, this example demonstrates how you can add custom commands to the report designer menu at runtime to provide better integration with your application. In the example, the custom Save&Close menu command is introduced, which redirects you to the catalog page after saving the report.

 
See also:
T190370: How to integrate the Web Report Designer into an MVC web application
T227679: ASPxReportDesigner - How to create an ASP.NET End-User reporting application with the filesystem report storage managed by the ASPxFileManager control

Question Comments

Added By: Sergey Kostrikov at: 7/10/2015 6:41:00 AM    

Can't understand. Where u take report.save()? what is report and what is method save()? Is any reference of JS objects and methods?

Added By: Vasily (DevExpress Support) at: 7/10/2015 7:54:31 AM    Hello Ruslan ,

To process your recent post more efficiently, I created a separate ticket on your behalf: T265741: How to integrate the Web Report Designer into a web application. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.Added By: Subhash Makkena at: 10/22/2015 8:38:15 AM    

Is there a way i can implement a custom drag and drop to canvas tool in the left hand side?
My requirement is, instead of drag and drop Chart into canvas, i want to provide 4 types of chart icons in the toolbox. And be able to drag and drop each kind of chart individually.

Added By: Jannet (DevExpress Support) at: 10/22/2015 8:53:30 AM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T303410: Web Report Designer - Is there a way i can implement a custom drag and drop to canvas tool in the left hand side. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

ASPxGridView - How to return the number of visible data rows excluding group rows

$
0
0

To change the number of visible data rows excluding group rows, do the following:

- Define the TotalSummary item:

[ASPx]
<TotalSummary><dx:ASPxSummaryItemFieldName="City"SummaryType="Count"ShowInColumn="City"DisplayFormat="{0} Item(s)"/></TotalSummary>

- Handle the grid's BeforeGetCallbackResult, PreRender, and DataBound events;

- Call the ASPxGridView.GetTotalSummaryValue to obtain the number of rows;

- Set this value as SettingsPager.Summary.Text.

Question Comments

Added By: Groupcare A/S at: 10/22/2015 11:06:54 AM    

I have written this as an extension method.
It expects that a KeyFieldName is set if it should work...

public static void FixGridItemCount(this ASPxGridView grid)
       {
           if (string.IsNullOrWhiteSpace(grid.KeyFieldName))
           {
               return;
           }
           grid.DataBound += FixGridItemCountEventHandler;
           grid.PreRender += FixGridItemCountEventHandler;
           grid.BeforeGetCallbackResult += FixGridItemCountEventHandler;
           var firstKeyFieldName = grid.KeyFieldName.Split(';').FirstOrDefault();
           if(firstKeyFieldName != null)
           {
               grid.TotalSummary.Add(new ASPxSummaryItem
                                     {
                                         FieldName = grid.KeyFieldName,
                                         SummaryType = SummaryItemType.Count,
                                     });
           }
       }   
                                                
       private static void FixGridItemCountEventHandler(object sender, EventArgs e)
       {
           var grid = sender as ASPxGridView;
           if(grid != null)
           {
               if (string.IsNullOrWhiteSpace(grid.KeyFieldName))
               {
                   return;
               }
               var firstKeyFieldName = grid.KeyFieldName.Split(';').FirstOrDefault();
               if (firstKeyFieldName != null)
               {
                   var asPxSummaryItem = grid.TotalSummary[firstKeyFieldName];
                   if (asPxSummaryItem != null)
                   {
                       var itemCount = (int) grid.GetTotalSummaryValue(asPxSummaryItem);
                       grid.SettingsPager.Summary.Text = MembercareGlobal.GridViewPagerSummaryText.Replace("[itemCount]", itemCount.ToString());
                   }
               }
           }
       }

Added By: Helen (DevExpress Support) at: 10/22/2015 10:42:06 PM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T303554: ASPxGridView - How to return the number of visible data rows excluding group rows. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

How to make PopupControl stay open after submitting a form using Ajax.BeginForm

$
0
0
This example demonstrates how to use the Ajax.BeginForm helper inside PopupControl to submit data asynchronously.
 

How to customize an XPO business model at runtime (Example)

$
0
0

Sometimes there is a requirement to extend existing business classes from other libraries, add new members, etc.

For instance, you have an assembly where you have declared your persistent classes. Now, you want to use these classes in your XAF application.

Note that to use the types from external assemblies, you should add them to your business model. To do that, you should use the Business Classes section of the Module Designer.


For instance, to force XAF to create navigation items for business classes, usually you can mark them with the DevExpress.Persistent.Base.DefaultClassOptionsAttribute, but what to do if your classes "live" in a separate assembly, which has no references to DevExpress.ExpressApp assemblies.

What to do? In this instance, the XafTypesInfo / XPDictionary customization may be helpful. Currently in XAF using this approach, you can add new attributes to your classes and their members, declare new associations, etc. The only thing, which is not currently supported in XAF, by default, is the capability to declare new classes "on the fly" via customization of the XafTypesInfo / XPDictionary. 

IMPORTANT NOTES

1. By design you cannot dynamically add or remove the OptimisticLocking and DeferredDeletion attributes.
2. Adding custom members for Domain Components (DC) should be done on the XafApplication.SettingUp event as described at How do I define a custom member for a domain component (DC) at runtime?.

3. For XAF versions older than 15.1.4 you cannot dynamically establish an association between two persistent classes via the XafTypesInfo API. Use the XPDictionary API instead as shown in this example.

Starting with v15.1.4, use the solution described in the eXpressApp Framework > Concepts > Business Model Design > Types Info Subsystem > Customize Business Object's Metadata > Create Associations in Code article.


See also:
How to: Access Business Class Metadata

Question Comments

Added By: Denis Sikic at: 11/15/2013 5:58:17 AM    

Update the MyXPOClassLibrary project from Framework 3.0 to 4.0, in order to compile.


ColorPickEdit - How to change the More Colors glyph

$
0
0
This example illustrates how to change the "More Colors" glyph

How to use document variable (DOCVARIABLE) fields

$
0
0

This example illustrates the use of a DOCVARIABLE field to provide additional information which is dependent on the value of a merged field. This technique is implemented so each merged document contains a weather report for a location that corresponds to the current data record.

NB: We do not provide code for retrieving weather information. You can implement a custom weather information provider.

The location is represented by a merge field. It is included as an argument within the DOCVARIABLE field. When the DOCVARIABLE field is updated, the DevExpress.XtraRichEdit.API.Native.Document.CalculateDocumentVariable event is triggered. A code within the event handler obtains the information on weather. It uses e.VariableName to get the name of the variable within the field, e.Arguments to get the location and returns the calculated result in e.Value property.
The MailMergeRecordStarted event is handled to insert a hidden text indicating when the document is created. 
The MyProgressIndicatorService class is implemented and registered as a service to allow progress indication using the ProgressBar control.

ASPxGridView - How to change a default editor to ASPxGridLookup in FilterRow via FilterTemplate

$
0
0

In some cases, when the default filter row editor's functionality is not enough, you can provide custom filter cell content using the FilterTemplate.

In this example, a default cell editor is replaced with the ASPxGridLookup control. The control's ValueChanged client-side event is used to send a callback to the server side, invoking the grid's CustomCallback event. In the event handler, a filter criteria is created and applied to the grid using the ApplyFilterToColumn method.

Question Comments

Added By: jasanguineti at: 1/13/2014 7:12:39 AM    

Please how set it filtertemplate in runtime?

thanks very much.

Added By: Ruslan (DevExpress) at: 1/13/2014 8:26:17 AM    

It's quite simple.
You need create a class that implements the ITemplate interface and assign template object to the GridViewDataColumn.FilterTemplate property.

[C#]
protectedvoidGrid_Init(objectsender,EventArgse){    vargrid=(ASPxGridView)sender;    grid.DataColumns["CategoryName"].FilterTemplate=newCustomFilterTemplate();}...publicclassCustomFilterTemplate:ITemplate{    publicvoidInstantiateIn(Controlcontainer){        varlookup=newASPxGridLookup();        lookup.ID="Lookup";        container.Controls.Add(lookup);    }}

 

[VB.NET]
ProtectedSub Grid_Init(ByVal sender AsObject, ByVal e As EventArgs)     Dim grid = CType(sender, ASPxGridView)     grid.DataColumns("CategoryName").FilterTemplate = New CustomFilterTemplate()EndSub ...PublicClass CustomFilterTemplateImplements ITemplate     PrivatepublicSub InstantiateIn(ByVal container As Control)         Dim lookup = New ASPxGridLookup()         lookup.ID = "Lookup"         container.Controls.Add(lookup)     EndSubEndClass

How to create a ChartControl descendant to provide the annotation feature

$
0
0
This example demonstrates how to create a ChartControl descendant with the Annotations collection. The AnotationPresenter class is used to show an annotation item inside an extra layer - the AnnotationPanel class instance. 

How to generate a document layout from scratch

$
0
0
This example shows the PDF Document Creation API that is used to programmatically generate a document layout.

How to load an MS Access Database file into the SpreadsheetControl's document

$
0
0

This example demonstrates how to extend the list of supported files which is displayed in the "Open File" dialog with the "MDB" file format while loading a document into the SpreadsheetControl.


To extend this list, a custom AccessDBDocumentImporter class was implemented. To add this functionality into an existing project, simply execute the SpreadsheetControl.ExtendOpenFileCommand method:

[C#]
spreadsheetControl1.ExtendOpenFileCommand();

To load data from an MS Access Database file, a corresponding extension LoadMSAccessFile method was implemented. This method can be used for the SpreadsheetControl's document, as well as the Workbook instance.

How to implement a custom LookUpEdit supporting Server Mode

$
0
0

The current LookUpEdit version does not allow using Server Mode datasources. This example demonstrates how to create a custom editor that allows using them.

Question Comments

Added By: Andrew Thornton at: 7/19/2013 10:32:51 AM    

Hi,

Just upgraded to 13.1.5, and this no longer compiles. Quite a few undocumented things looked to have changed.
Can we have a 13.4/5 version that works please?

Thanks.

Added By: Justin Zeng at: 4/17/2014 4:32:51 AM    

It seems many problem, can this function to be support in new version ?

Added By: Ivan (DevExpress Support) at: 4/27/2014 10:42:28 PM    

Hi Justin,

We cannot guarantee that this functionality will be available in the latest version. For now, you can try to extend this example manually. If you face difficulties doing this, do not hesitate to contact us.

Added By: Viktor Faerman at: 5/9/2014 1:57:04 AM    

Hi Alex,

how to implement this custom editor with MVVM?
Thanks, Viktor

Added By: Michael Ch (DevExpress Support) at: 5/9/2014 4:14:02 AM    Hello,

I have created a separate thread for your questions: How to implement a custom editor from the E4560 example with MVVM. Please refer to it for future discussion.

Thanks,
Michael

Added By: David Lemieux at: 8/12/2015 10:09:43 AM    

This probably does the trick for standalone lookup editors, but I have doubts about using this inside a grid. If my understanding of both the code below and the grid's mechanics is correct, a query will be issued for each and every cell for which such an editor is present. Therefore, if you have 20 records on screen with five columns each having such an editor, that's a hundred of connections opening, querying and closing right there. And EVEN with just ONE column, it will still be under-performing when it will be sorted, grouped or filtered. Even for the non-virtualized rows.

This needs a proper solution. Urgently.

Added By: Ivan (DevExpress Support) at: 8/13/2015 3:01:37 AM    

David, you are correct. The editor we implemented in this example is not designed to be used inside GridControl. With the current implementation, a new source/context will be created for each visible grid cell. Please refer to my comment in the LookUpEdit - server mode support ticket, where I clarified our plans regarding this feature.

Added By: Alexei Corduneanu 2 at: 9/4/2015 7:27:11 AM    

I'm trying to use this approach together with WcfInstantFeedbackDataSource.
As SelectedItem I'm setting the Item I've saved in the database previously. And I'm having a problem with loading the LookUpEdit value back because I'm getting "Value cannot be converted" error. I guess it's happens because the Item is not present in the datasource.
What should be a correct way to load the value back to this control?

Added By: Ilya (DevExpress Support) at: 9/4/2015 12:30:46 PM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T286248: How to modify E4560 so it properly works with a WcfInstantFeedbackDataSource. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

Added By: Alexei Corduneanu 2 at: 10/6/2015 7:57:35 AM    

How could I achieve multiple selection using this control?

Added By: Ilya (DevExpress Support) at: 10/6/2015 11:27:36 AM    

Hi,
I have extracted your inquiry into a separate thread: How to enable multiple row selection in the LookUpEdit implementing Server Mode (E4560). Let's continue the discussion there.

Added By: Billy P at: 10/26/2015 7:40:23 PM    

How can I assign a null value when the text is cleared, like the behavior of AssignNullValueOnClearingEditText for ComboBoxEdit?

Added By: Michael Ch (DevExpress Support) at: 10/26/2015 10:07:05 PM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T304633: How to assign a null value when the text is cleared. This ticket is currently in our processing queue. Our team will address it as soon as we can.


How to generate a sequential and user-friendly identifier field within an XPO business class

$
0
0

Scenario

Orders, articles or other business entities often require that you have user-friendly Id or Code fields that end-users can memorize and use during phone conversations. They are usually sequential, but some gaps can be allowed as well (e.g., when an order is deleted). Refer to this StackOverFlow thread for more information on this common scenario, and a possible implementation.

Steps to implement

1. Add a new business class to your platform-agnostic module, and  call the static DevExpress.Persistent.BaseImpl.DistributedIdGeneratorHelper.Generate method from the AfterConstruction, OnSaving or other appropriate places within your persistent class or even Controller as shown in the Solution2.Module\BusinessObjects\Order.xx file. Depending on your business requirements, you can implement a readonly persistent or editable property where the generated value will be stored as well as check various conditions before generating the next sequence (e.g., string.IsNullOrEmpty(currentSequenceProperty) - to avoid double assignments, Session.IsNewObject(this) - to check whether the object is new, !(Session is NestedUnitOfWork) - to check whether the object is being saved to the database and not to the parent session, security system checks as per this blog post, etc.)

2. Build your platform-agnostic project and double-click on the Solution2.Module\Module.xx file to invoke the Module Designer;

3. Refer to the Exported Types section within the designer and expand the Referenced Assemblies | DevExpress.Persistent.BaseImpl node;

4. Select and press the space bar on the OidGenerator and ServerPrefix nodes to include these types into the business model of your module:

IMPORTANT NOTES
1. The DistributedIdGeneratorHelper class demonstrated in this solution creates the IDGeneratorTable and ServerPrefix tables to store the information about the last sequential number of a type.
Although this particular solution is simpler to implement and maintain (as it uses built-in XAF classes) than 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 (XAF) example, it is pretty safe and should also work in the most typical business scenarios (except for the middle-tier Application Server scenario, because the Session.DataLayer property is not initialized in this case).
2. If you have validation rules for your business class, the OnSaving method (and thus the sequence generation) is called only after all validation is passed. However, in rare cases, if a database related error is thrown during the first save and then the form is re-saved, the OnSaving method may be called again and a new sequence can be generated. This may lead to gaps in sequential numbers, which is not always allowed by business requirements (e.g., government regulations). To avoid this, you can use a more complicated solution from 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 (XAF) example or implement a database-level solution to handle such situations (e.g., using triggers).

3. You can find functional EasyTest scripts for this scenario in the Solution2.Module\FunctionalTests\E4904.ets file.

Question Comments

Added By: Gareth- at: 10/2/2013 5:58:17 AM    

Thanks, works perfectly - I've seeded the ID by manually changing the [Oid] in the IDGeneratorTable, do I need to worry about the [OptimisicLockField] or will this update automatically?

Added By: Dennis (DevExpress Support) at: 10/2/2013 7:10:50 AM    

@Gareth: No, you do not need to care about the OptimisticLockField.

Added By: MohammedFarooq at: 12/2/2013 1:07:31 AM    

Hi,

The code is really helpful but it increments the value of code even if the record is deleted! How can we stop the code to increase its value when a record is deleted?

Added By: MohammedFarooq at: 12/2/2013 1:25:16 AM    

I manage to figure out the solution. I have just added the IsDeleted checking and it worked like a charm!!!

    Protected Overrides Sub OnSaving()
        If (Not IsDeleted) Then
             Me.codeCore = String.Format("N{0:D6}", DistributedIdGeneratorHelper.Generate(Me.Session.DataLayer, Me.GetType().FullName, String.Empty))
        End If
        MyBase.OnSaving()
    End Sub

Added By: Dennis (DevExpress Support) at: 12/2/2013 1:26:50 AM    

@Mohammed: Yes, your solution is correct. I will consider updating this example accordingly. Thanks for your input in this regard.

Added By: rushdan . at: 11/6/2014 12:02:48 AM    

Hallo

I do not understand about explanation. What I know is, after I run the application, then save the data , it will execute Code number automatically.

Is it this example to show how to execute auto increase number ? Thanks

Added By: Dennis (DevExpress Support) at: 11/6/2014 2:00:43 AM    

@Rushdan: With the current implementation, the generation code is executed when the persistent object is being saved (OnSaving). I do not quite understand your last question. The functionality implemented in this example is well-detailed in the description and it can also be seen from simple code.

Added By: Andrew Bingham 2 at: 2/5/2015 12:40:25 AM    

"override its AfterConstruction method, as shown in the Solution2.Module\BusinessObjects\DomainObject1.xx file"

1. I cannot find the DomainObject1 file in the sample
2. The only BusinessObject is Order.cs which does not have an AfterConstruction method
3. What code need to go in AfterConstruction method?
4. What are the advantages / disadvantages compared to E2829?

Added By: Dennis (DevExpress Support) at: 2/5/2015 12:47:04 AM    @Andrew: Thanks for your feedback.
1-3. I've corrected this misprint in the description. 
3. This particular solution is simpler to implement than E2829.Added By: Vishwas Mokashi at: 4/21/2015 8:52:32 AM    

Is there any provision so that we can restart the Sequence Number after say an Year is completed?. Also, any way to give the start number for the sequence?.

Added By: Dennis (DevExpress Support) at: 4/21/2015 8:57:35 AM    

@Vishwas: Sure, you can do this. Technically, the information about the last sequence number is stored in the Oid column of the IDGeneratorTable table with the help of the OidGenerator persistent class. You can modify this data using either ADO.NET or XPO means.

Added By: Vishwas Mokashi at: 4/21/2015 9:02:11 AM    

Ok thanks Dennis...will try

Added By: MohammedFarooq at: 10/14/2015 2:37:53 AM    

Dear Dennis,

I have applied this logic in my project which also has validation enabled. Now the issue is, if the validation of the document fails while saving the new number is generated. And when the user saves the document again then a new number is generated as well.

Added By: Dennis (DevExpress Support) at: 10/14/2015 2:58:59 AM    @Mohammed: The original example has the if(string.IsNullOrEmpty(Code))  check that prevents multiple generations. Have you applied this code in your project? If this does not help, submit a separate ticket and attach your problematic sample so we can assist you further.Added By: MohammedFarooq at: 10/14/2015 5:03:57 AM    

You hit a bull's eye! I didn't have the  if(string.IsNullOrEmpty(Code)) in my code.

Was it added recently? Because i followed this example before and somehow i missed it.

Added By: Dennis (DevExpress Support) at: 10/14/2015 5:18:38 AM    You're always welcome. AFAIK, I added it a year ago or so.

How to generate and assign a sequential number for an XPO business object within a database transaction, while being a part of a successful saving process (XAF)

$
0
0

This version 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 example is primarily intended for XAF applications, because all the required operations to generate sequences are managed within the base persistent class. However, this code can be used in a regular non-XAF application based on XPO, as well.

For more convenience, this solution is organized as a reusable module - GenerateUserFriendlyId.Module, which you may want to copy into your project 'as is' and then add it as required via the Module or Application designers. This module consists of several key parts:

1. Sequence, SequenceGenerator, and SequenceGeneratorInitializer - auxiliary classes that take the main part in generating user-friendly identifiers.

Take special note that the last two classes need to be initialized in the ModuleUpdater and ModuleBase descendants of your real project.


2. UserFriendlyIdPersistentObject - a base persistent class that subscribes to XPO's Session events and delegates calls to the core classes above.


3. IUserFriendlyIdDomainComponent - a base domain component that should be implemented by all domain components that require the described functionality. Take special note that such derived components must still use the BasePersistentObject as a base class during the registration, e.g.:

[C#]
XafTypesInfo.Instance.RegisterEntity("Document",typeof(IDocument),typeof(BasePersistentObject));

4. Address, Contact, and IDocument are business objects that demonstrate the use of the described functionality for XPO and DC respectively.
Take special note that a required format for the user-friendly identifier property in these end classes is defined within an aliased property (AddressId in the example below) 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:

[C#]
[PersistentAlias("concat('A', ToStr(SequentialNumber))")]publicstringAddressId{get{returnConvert.ToString(EvaluateAlias("AddressId"));}}

IMPORTANT NOTES

1. If your connection string contains the Password parameter, then rework the SequenceGeneratorInitializer.Initialize method to not use the XafApplication.ConnectionString or XafApplication.Connection.ConnectionString properties, because XAF encrypts the specified password for safety reasons. Instead, either specify the connection string directly or read it from the configuration file.
2. The sequential number functionality shown in this example does not work with shared parts (a part of the Domain Components (DC) technology) in the current version, because it requires a custom base class, which is not allowed for shared parts.
3. This solution is not yet tested in the middle-tier and SecuredObjectSpaceProvider scenario and most likely, it will have to be modified to support its specifics.
4. As an alternative, you can use a more simple solution that is using the DistributedIdGeneratorHelper.Generate method as shown in the FeatureCenter demo ("%Public%\Documents\DXperience 13.X Demos\eXpressApp Framework\FeatureCenter\CS\FeatureCenter.Module\KeyProperty\GuidKeyPropertyObject.cs" ) or at How to generate a sequential and user-friendly identifier field within a business class

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

OfficeNavigationBar - How to hide a peek form on moving the mouse

$
0
0

This example illustrates how to hide a peek form when the mouse pointer leaves it. The main idea of this approach is to check if the mouse pointer is located within the peek form or OfficeNavigationBar boundaries. To simplify the solution, we created a special OfficeNavigationBarHelper class. To enable this feature, call the OfficeNavigationBarHelper.SetPeekFormBehavior method. 

DXGrid - How to show group summaries in a group footer

$
0
0

This example demonstrates how to create group footers in the grid and show summaries there. For this, you will need to create a TableView descendant and use custom templates for ordinary and group rows. Please note that the demonstrated approach has certain limitations:

1) It works only for one-level grouping;

2) The row indicator for a row that contains a group footer will be drawn both for the row and for the footer;

3) The group footer will replicate summaries that can be shown in the group row;

4) It is necessary to create a group footer template for each theme used in the application.

Question Comments

Added By: John Stewart 007 at: 10/27/2015 8:56:02 AM    

Example code throws InvalidOperationException on click of expland (+ button).
Here is the details error message
CellItemsControl (that is typically used in DefaultDataRowTemplate) is not supported in the grid's optimized mode. To learn more about the grid's optimized mode, see http://go.devexpress.com/xpf-optimized-mode.aspx

How to show an error text for editors in the EditFormTemplateContainer.

$
0
0

This sample illustrates how to show an error text that is set for a column in the server-side RowValidating event handler within the error frame of the corresponding editor if the editor is placed in the EditFormTemplateContainer of ASPxGridView.

Question Comments

Added By: Rapu Noa at: 10/27/2015 9:36:04 AM    

This is extremely complicated, hard to understand and hard to maintain. For all practical purposes this functionality is in efect not supported. Really, this looks more like a bad joke than anything else.

Added By: Helen (DevExpress Support) at: 10/27/2015 12:36:06 PM    

Hello,

I feel concerned that this approach is not working for you. At this moment, event data of the RowValidating event does not contain values from template editors. So this solution is the only available way to use this event with the Edit Form template. If you face difficulties with this code, feel free to submit a ticket describing your scenario in greater detail. We may be able to suggest a workaround for your case.

Viewing all 7205 articles
Browse latest View live


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