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

ASPxGridView - How to merge cells horizontally

$
0
0
Starting with version v2016 vol 1 (v.16.1), it became possible to merge cells using functionality available out of the box. Refer to the Cell Merging demo for more information. This one provides only vertical merging.

This example demonstrates a possible way of merging cells in the ASPxGridView control horizontally when adjacent cells in a row with the same values are merged. To do this, you can use the HtmlRowPrepared and HtmlDataCellPrepared events.
Please keep in mind that functionality such as batch edit mode and fixed columns may not work as expected.

How to implement data paging

$
0
0

Silverlight supports the data paging mechanism natively. In the meantime, there are no easy approaches to implementing the IPagedCollectionView interface in WPF.


The easiest way to implement data paging is to change the grid's ItemsSource when the page index is changed. This example contains special attached behavior that allows you to enable this feature with ease.

See Also:
How to support paging in DXGrid by implementing the IPagedCollectionView interface

Question Comments

Added By: Ravickumar Murugesan at: 8/23/2013 3:00:35 PM    

With this implementation the search behavior is not normal.

Added By: Alexander (DevExpress Support) at: 8/25/2013 11:27:33 PM    

Hello,

I have checked the Search Behavior with this solution using version 13.1.6, and it appears that everything works as expected. Searching operates only for the current page. If you have other behavior on your side, would you please describe the issue in greater detail?
P.S. Please create a separate ticket to clarify this moment. If we find an issue with the provided solution, we will update it.

Added By: f22raptor at: 2/4/2014 9:53:13 AM    

I getting NULL exception at this line:
 DataPager.ItemCount = Sources.Count;

Added By: Michael Ch (DevExpress Support) at: 2/5/2014 6:19:48 AM    

Hello,

We have moved your question to a separate thread: Q466351 thread. Please refer to it for further discussion.

Added By: kumar gaurav 8 at: 8/7/2014 11:51:08 PM    

this solution is not working because the GetValue(sourceproperty) gives null

Added By: Alexander (DevExpress Support) at: 8/8/2014 2:37:17 AM    

Hi Kumar,

I've noticed that there is a separate thread with the same question from you: How to implement paging in dxg:GridControl using dxe:DataPager. We will answer in that ticket as soon as possible. Please give us some time.

Added By: Candy lei at: 10/15/2014 1:02:17 AM    

How could I add the datapager in the footer of the gridControl. I add it to the FooterTemplate of the tableview , but it can't works well. What should I do?

Added By: Nadya (DevExpress Support) at: 10/15/2014 3:01:53 AM    

Hi, Candy

We have moved your question to a separate thread: T161457 - How to add DataPager in the GridControl footer . Please refer to it for further discussion.

Added By: Sapient IT GSS at: 4/14/2015 9:43:28 PM    

Not getting you completely, can you please explain by an example instead of old post's link.

Added By: Alex Chuev (DevExpress Support) at: 4/15/2015 12:18:58 AM    Hi,

We try discuss additional scenarios in separate posts in order not to overload this thread. Let's continue our conversation in the ticket that you created earlier: T229634 - Need Help in Data Pager Implementation.

Thanks,
AlexAdded By: Madhuri Ambekar at: 7/9/2017 11:02:25 PM    Hi,

I am implementing the same sample code in my application only thing that is been changed is binding. I am binding the list in my Init() instead of constructor so pagination is shown but data not displayed in grid

As data always change so i have to bind in Init().

kindly provide solution as soon as possible

Regards,
Madhuri Added By: Madhuri Ambekar at: 7/9/2017 11:58:39 PM    Also, when i bind my original grid list to data pager then pagination is displayed but data not displayed in grid

And when i modify the list i.e. i put my list items in TestDataList(as shown in sample code) and bind the
PagedCollection then pager is disabled

Added By: Andrey Marten (DevExpress Support) at: 7/10/2017 1:33:03 AM    

Hello,

I've created a separate ticket on your behalf (T533928: How to bind ItemsSource on demand when pagination is used in GridControl). It has been placed in our processing queue and will be answered shortly.

Thanks,
Andrey

Added By: Fakhru Izuh at: 11/28/2017 1:46:09 AM    Hi,


If I add more pages to this example, width of DataPager doesn't change to display more page numeric. E.g. if I have 10 pages, pager display would be like, < 1 2 3 4 ... >.

How can I have display pager with more page numerics like, < 1 2 3 4 5 6 7 ...>   

How to customize the Appointment Dialog using View Model API

$
0
0

View Model API enables you to customize dialog element characteristics (values, availability, and a layout) as needed, without the necessity of overriding ASPxScheduler's commands and copying dialog form templates (UserControls) into your project.

This example illustrates how to customize the Appointment Dialog content (changing the editor's type, visibility, captions, and font settings) using Model View API as described in the How to customize Appointment Dialog using View Model API topic. 

How to save/restore a palette name

$
0
0

 

This example demonstrates how to save the current skin and palette between sessions. For this, the application settings are used.

How to create edit form templates dynamically

$
0
0

This example illustrates how to add editors within the EditFormTemplateContainer of ASPxGridView programmatically by implementing the ITemplate interface.

See also:
ASPxGridView - How to load UserControl within EditFormTemplate at runtime

Question Comments

Added By: Esa Niemi at: 10/28/2015 7:17:19 AM    

Could you add some comments? It takes unnecessarily long from a devexp-noob to parse what is going on.

Added By: Lisa Bencic at: 11/28/2017 8:05:23 AM    This whole topic fails when you have a detail inside a master, you cannot reference the (child) grid view during Page Load like that.   Most solutions I am looking at (to Hide a field during Edit but not during New) do not work for that reason.

ASPxGridView - How to export multiple grids to separate documents and download them at once

$
0
0
By default, the HTTP protocol and client browsers do not provide the capability to download multiple files at once via a single Response or pass multiple responses to a single Request.
As a solution, it's possible to put multiple exported documents into a single zip archive and send this archive to the end-user.
Obtain the exported documents' memory streams by using the ASPxGridViewExporter's  WriteCsv/WriteDocxWritePdfWriteRtf/WriteXls/ WriteXlsx methods and use the Compression Library API to add these documents to a zip archive (e.g., see How to: Compress .NET Stream). Then, write the resulting archive memory stream to the Response to allow a user download it.

How to customize the Appointment Dialog using View Model API (working with custom fields)

$
0
0

View Model API enables you to customize dialog element characteristics (values, availability, and a layout) as needed, without the necessity of overriding ASPxScheduler's commands and copying dialog form templates (UserControls) into your project.

This example illustrates how to customize the Appointment Dialog content for working with custom fields using Model View API as described in the "How to customize the Appointment Dialog using View Model API (working with custom fields)" topic. 

How to edit the ASPxGridView without the edit form (External Edit Form)

$
0
0

This demo illustrates how to edit the ASPxGridView control without the edit form via a set of external editors residing near the GridView.

See Also:
Editing in a new window


How to copy a page from one document to another PDF

$
0
0
This example shows how to extract a page from one PDF document and insert it to another PDF. 
Question Comments

Added By: Brendon Muck [DevExpress MVP] at: 11/27/2017 9:39:29 AM    The code sample here appears to not be doing any sort of copy/extract of a page. The 'Implementation Details' are totally inaccurate as well.Added By: Yulia (DevExpress Support) at: 11/27/2017 10:48:02 AM    Hello Brendon,

Thank you for your feedback. We will correct the example shortly. 

How to initialize a new row when only the editor is shown

How to bind ASP.NET MVC Dashboard to an Object Data Source and provide data using a custom fill service

How to: Allow a user to select the authentication type at runtime

$
0
0

To accomplish this task, you should create a new authentication type, inherited from the AuthenticationBase, and combine the code of the AuthenticationStandard and AuthenticationActiveDirectory classes in it. Additionally, you should create a custom logon parameters class with a property, allowing users to select the authentication type.

See Also:
How to enable the ResetPasswordController and ChangePasswordController Actions (Reset and Change Password) when ActiveDirectoryAuthentication is used

Question Comments

Added By: Raoulw at: 5/28/2012 11:14:21 AM    

Sample broken.

                            System.Reflection.MethodInfo mi = typeof(SecurityStrategyBase).GetMethod("InitializeNewUser", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

Should be:

                            System.Reflection.MethodInfo mi = typeof(SecurityStrategyBase).GetMethod("InitializeNewUserCore", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);

In 11.2.11

Raoul.

Added By: Apostolis Bekiaris (DevExpress) at: 7/8/2013 10:02:55 PM    

Added to www.eXpandFramework.com 13.1.5.1 enjoy!

Added By: Osman Mumcu at: 4/1/2014 11:38:19 PM    

Hello,
Thank you very much for this great functionality.
However I want the "UserName" and "Password" fields to be DISABLED , when the "ActiveDirectory" checkbox is checked. If it is unchecked then these values should be enabled again. It will be a better approach for the end users. How can I accomplish this. I tried using the "Appearance" module. But it didn't work.
For Example:
I put below Attribute above the UserName property
[Appearance("DisablePassword", Enabled = false, Criteria = "UseActiveDirectory",Context="DetailView")]
But didn't work.

Thanks.

Added By: Svatopluk Ulicny at: 4/9/2014 3:01:49 AM    

Hi, I has same question as Yahya Mum, is it possible?
Thanks

Added By: Carlitos at: 9/12/2014 7:17:36 AM    

I was having the same issue as Yahya and Martin. I solved it by merging codes from E2371, E3931 and https://documentation.devexpress.com/#Xaf/CustomDocument3475

Works like a charm now.

Added By: Michael (DevExpress Support) at: 9/15/2014 7:38:29 AM    To make dynamic appearance rules work correctly on the logon form, in addition to the code provided in the Use Conditional Appearance on the Logon Form article, you need to create a controller (and add it to the CreateLogonWindowControllers method of course) that will refresh the appearance when a property is changed.
[C#]
publicclassMyLogonController:ViewController<DetailView>{publicMyLogonController(){TargetObjectType=typeof(AuthenticationCombinedLogonParameters);}protectedoverridevoidOnActivated(){base.OnActivated();PropertyEditoreditor=View.FindItem("UseActiveDirectory")asPropertyEditor;if(editor!=null){editor.ValueStored+=newEventHandler(editor_ValueStored);}}voideditor_ValueStored(objectsender,EventArgse){AppearanceControllerappearanceController=Frame.GetController<AppearanceController>();if(appearanceController!=null){appearanceController.Refresh();}}}

We will address this issue in the future when improve the support for non-persistent objects.

How to create the HTML5 JavaScript Web Dashboard application

How to generate and assign a sequential number for an XPO business object within a database transaction as part of a successful saving process (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 How to implement a user-friendly identifier field with sequential values in 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){GenerateUserFriendlyId.Module.Utils.SequenceGenerator.Initialize(this,args.ConnectionString);//!!!...}

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 as shown below:

[C#]
privatestaticvoidserverApplication_CreateCustomObjectSpaceProvider(objectsender,CreateCustomObjectSpaceProviderEventArgse){GenerateUserFriendlyId.Module.SequenceGenerator.Initialize((XafApplication)sender,e.ConnectionString);

In the same code file, locate the serverApplication.Dispose(); line and move to the end of the Main or OnStop methods in the Console or Windows Service applications respectively (in the latter case, the "serverApplication" variable must also be declared in the higher scope).


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 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 
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.
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

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 How to implement a user-friendly identifier field with sequential values in an XPO business class KB article.

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

$
0
0

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

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 in OnSaving. 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.)

Take special note that you can use any strings as the "seqType"  and "serverPrefix" (optional) parameters that allow you to run named sequences in parallel (these parameters determine criteria for  updating right sequences). In the demo, I am just using the full persistent type name and a custom prefix, which can be changed as you need:

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 node to include this persistent type into the business model of your module:

 

IMPORTANT NOTES
1. The DistributedIdGeneratorHelper class demonstrated in this solution creates the IDGeneratorTable table to store the information about the last sequential number of a type. You can learn more on how this works from its source code at "C:\Program Files (x86)\DevExpress 1X.X\Components\Sources\DevExpress.Persistent\DevExpress.Persistent.BaseImpl\IDGenerator.cs".
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.
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.  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.

4. You can find functional EasyTest scripts for this scenario in the Solution2.Module\FunctionalTests\E4904.ets file.
5. You can specify the initial sequence value manually: either by editing the IDGeneratorTable table in the database or using the standard XPO/XAF means by manipulating the DevExpress.Persistent.BaseImpl.OidGenerator objects. Another simpler solution would be using a different server prefix, e.g. "2017" or "2018" to start numbering with 1 again.

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.Added By: Paul Kubb at: 3/16/2016 2:14:58 AM    Would you please describe more in detail about serverprefix table? how and when to use it?
I cannot find any documentation about it also.Added By: Dennis (DevExpress Support) at: 3/17/2016 1:57:56 AM    

@Paul: It was a mistake in the original description, because this table is actually unused by the DistributedIdGeneratorHelper class. Please accept my apologies for the confusion. As for the "string serverPrefix" parameter of the Generate method, it allows you to run several sequences in parallel. Refer to the "C:\Program Files (x86)\DevExpress 1X.X\Components\Sources\DevExpress.Persistent\DevExpress.Persistent.BaseImpl\IDGenerator.cs" source file for more details.

Added By: Paul Kubb at: 8/4/2016 9:44:09 AM    I have read a source file and have several questions aboud DistributedIdGeneratorHelper.Generate():

1.  it seems like you intend to create a separate new session, attempt to save it to the database separately until success and return its Oid. Why can't we use the bo's existing session here?

2. by this design, do you intend to avoid some multi-user problem or something? if so, please explain why having a separate session will overcome it

3. if the OidGenerator is saved successfully in a separate session but the main bo's save event is dead, will the OidGenerator's save event be rolled back? or will we have a jumpy running number instead?

thanks in advance

Added By: Dennis (DevExpress Support) at: 8/5/2016 7:12:09 AM    

@Paul:
A1-2: Your understanding of class design is correct. A separate session will help to avoid concurrency issues in a multi-user environment: if another user generated a new number while you were saving your own, the locking exception occurs and a new attempt to generate the next number for you starts in the loop.
A3:No, it will not. See my answer in the T304004 ticket for more details.

Added By: wang yu 4 at: 9/23/2016 12:59:54 AM    does it support middle tier ?Added By: Dennis (DevExpress Support) at: 9/23/2016 2:13:47 AM    

@Wang: As in the example's description, the DistributedIdGeneratorHelper class currently does not support the middle-tier Application Server scenario, because the Session.DataLayer property is not initialized in this case.

Added By: 13 chi at: 10/3/2016 2:21:46 AM    That fix for middle-tier doesn't work well.
[C#]
newSession(sourceSession.ObjectLayer).DataLayer;
still returns null.
Added By: Dennis (DevExpress Support) at: 10/4/2016 2:41:06 AM    @13 chi: Thanks for your report and please accept my apologies for the inconvenience here. I will update the article with a better solution as soon as it is available.Added By: Dennis (DevExpress Support) at: 10/4/2016 10:29:13 AM    @13 chi: I've updated the E4904 example classes for the middle-tier Application Server scenario (see additional checks in the OnSaving method). Note that in this scenario, the generated sequence number will appear in the WinForms DetailView only after a manual refresh (i.e., it will be empty right away after saving a record), because the sequence is generated on the server side only and is not passed to the client.Added By: Konstantin B (DevExpress) at: 12/4/2017 1:21:21 AM    Update: This example illustrates one of the possible approaches to implementing an identifier field with sequential values. Alternate approaches are listed in the How to implement a user-friendly identifier field with sequential values in an XPO business class KB article.

GridView - How to implement cascaded combo boxes in the EditForm

$
0
0

This example is an illustration of the KA18675: MVC ComboBox Extension - How to implement cascaded combo boxes KB Article. Refer to the Article for an explanation.

UPDATED:

Starting with v16.1, it's not necessary to define the second combo box using the MVCxGridViewColumn.SetEditItemTemplateContent method to enable callbacks.
Use a new API instead:
MVCxGridViewColumn.EditorProperties 
MVCxColumnComboBoxProperties 
GetComboBoxCallbackResult 
 
You can find detailed steps by clicking the "Show Implementation Details" link below.

Question Comments

Added By: Cankut at: 8/26/2016 7:03:22 AM    Thanks for this great demonstration , i've used this in my project, could you upgrade this by using three cascaded combo boxes like Country, City and Street in MVC?Added By: Artem (DevExpress Support) at: 8/26/2016 8:13:07 AM    Hi,

You're welcome! I see you've asked the same question in the Cascade three thread. We'll reply to you there as soon as possible. Please refer to it for further correspondence.Added By: Yerko at: 11/29/2016 11:53:06 AM    Will this approach also work in Batch Editing and Updating with "cell" edit mode? Added By: Nataly (DevExpress Support) at: 11/29/2016 11:58:27 AM    

Hello,

I've created a separate ticket on your behalf (T456582: GridView - How to implement cascading combo boxes in Batch Edit mode). It has been placed in our processing queue and will be answered shortly.

Added By: Steve Lough at: 11/8/2017 8:22:08 AM    In the example, when you edit the first row in the grid and click the City combo box, it only has one entry with France selected as the country.  If you change the country to something else, then back to France, there are more entries in the City combo box.  Shouldn't this contain all of the entries for France without having to change the combo box first?Added By: Stason (DevExpress Support) at: 11/9/2017 7:14:49 AM    Hello Steve,


I've created a separate ticket on your behalf (T574572: GridView - Cascading Comboboxes - How to fetch data for a combobox when a user starts to edit a row). I will address it shortly.

Added By: Philippe MASSON at: 12/4/2017 6:14:14 AM    Hi,

Is there a way to achive a dynamic selection of values based on another column ? (NOT in edit mode !)
For example, for 2 columns: Countries and Cities. If I choose England, I want in the Cities column to have the cities from England. So, directly in the gridview columns (not datasource)

How to Create a Checked ComboBox

How to make the TreeList control look like a TreeView

$
0
0

The TreeList control provides support for a TreeView visual style, in which the control mimics the appearance of the .NET standard TreeView control. Starting from version 17.2, the TreeView visual style can be enabled using the single setting - TreeList.ViewStyle.

In versions prior to 17.2, you can emulate the TreeView visual style as follows:
- Hide column headers (set OptionsView.ShowColumns to False).
- Hide the indicator panel (set OptionsView.ShowIndicator to False).
- Hide the horizontal and vertical lines between cells (set OptionsView.ShowHorzLines and OptionsView.ShowVertLines to False).

How to customize a data store schema for SQL data sources

$
0
0

This example demonstrates how to customize a data store schema for a dashboard data source that uses a connection to the Northwind database.

In this example, the IDBSchemaProvider interface is implemented by a class that defines a custom data store schema containing two related tables. The GetSchema method returns tables and columns which will be included to a data store schema. 

To see the result, add a new query or edit the existing query.

Question Comments

Added By: Mariusz Muszalski at: 2/16/2015 3:31:54 AM    

I use ConfigureDataConnection event to provide connection details for my dashboard designer. The data source is OLAP (tabular). Can I use solution above to customize names of fields in field chooser?

Added By: Andrew Aks (DevExpress) at: 2/16/2015 5:29:48 AM    

This approach can be used only for SQL data sources. We will update the Provide a way to localize OLAP cube structure in Dashboard Designer request when a similar capability is added for OLAP data sources.

ASP.NET MVC Dashboard - How to customize a data store schema for SQL data sources

$
0
0

This example demonstrates how to customize a data store schema for a dashboard data source that uses a connection to the Northwind database.

In this example, the IDBSchemaProviderEx interface is implemented by a class that defines a custom data store schema containing two related tables. The GetSchema method returns tables and columns which will be included to a data store schema. 

To see the result, add a new query or edit the existing query.

Viewing all 7205 articles
Browse latest View live


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