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

How to implement multi-row editing in the ASP.NET ListView

$
0
0

The ASPxGridListEditor does not natively support multi-row editing. It is recommended to either use the single-row inline editing by setting the AllowEdit property of the ListView model to True in the Model Editor, or edit objects in a DetailView. The multi-row editing functionality is rarely required, but since our customers usually experience difficulties implementing it, I decided to create this example.

There are several examples on how to implement this functionality in the ASPxGridView without XAF. From my point of view, the How to perform ASPxGridView instant updating using different editors in the DataItem template example is the most appropriate for XAF, because:

- this approach can be easily implemented using runtime code

- we already use DataItem templates to show data in grid cells.


All functionality is implemented in a single controller - the MultiRowEditingController. It performs the following operations:

1. Creates an ASPxCallback control and adds it to a page. This control is used to send callbacks from client-side editors used in grid cells.

2. Replaces the default DataItemTemplate with a custom one (EditItemTemplate). The custom template is required to show editors for the user input in grid cells. This template is based on the DataItemTemplate class used in XAF by default. The only difference is that controls from this template are always in the Edit mode.

3. Assigns the client-side script that performs a callback when the value is changed to the editors added to grid cells via the custom DataItemTemplate. This is done in the editor's Init event handler, because at this moment, the NamingContainer that contains the key of the bound object is available.

4. Handles the callback sent from the client side and changes the value of a corresponding object's property.


I recommend that you review the following help topics for additional information:

Access Grid Control Properties
ASPxGridView.Templates Property
How to use custom ASPxGridView template in a Web XAF application


Important notes
We have not tested this solution under all possible scenarios, so feel free to modify and test the code to better suit your needs. It this example and its current limitations do not meet your requirements, check out the How to enable fast data entry in multiple rows for ListView on the Web (ASPxGridListEditor)? thread for alternative solutions.

Question Comments

Added By: Yuriy Konytskyy at: 6/3/2013 3:44:39 AM    

I doesn't work in v12.2.10

Added By: Anatol (DevExpress Support) at: 7/1/2013 4:19:13 AM    

I have updated the example. Please see implementation details for version 13.1.

Added By: Sandro Welter (Intelligix) at: 7/5/2013 3:02:00 PM    

I'm getting the error below.

The error occurred:
     Type: NullReferenceException
     Message: Object reference not set to an instance of an object.
     Data: 0 entries
     Stack trace:

Added By: Anatol (DevExpress Support) at: 1/10/2014 8:32:12 AM    

The NullReferenceException issue is solved.

Added By: PHN at: 1/30/2014 10:55:55 AM    

Hi,
I have some modifications to support ASPxDateTimePropertyEditor,ASPxLookupPropertyEditor:

using System;
using System.Linq;
using System.ComponentModel;
using System.Web.UI;

using DevExpress.ExpressApp.Web.Editors.ASPx;
using DevExpress.Web.ASPxGridView;
using DevExpress.ExpressApp.Web;
using DevExpress.ExpressApp.Editors;
using DevExpress.Web.ASPxClasses;
using DevExpress.ExpressApp.DC;
using DevExpress.Web.ASPxCallback;
using DevExpress.ExpressApp.Model;
using System.Web.UI.WebControls;
using DevExpress.Web.ASPxEditors;
using DevExpress.Xpo;
using DevExpress.ExpressApp;

namespace WebExample.Module.Web
{
    [ListEditor(typeof(object), false)]
    public class MultiEditASPxGridListEditor : ASPxGridListEditor
    {
        const String CallbackArgumentFormat = "function (s, e) {{ {0}.PerformCallback(\"{1}|{2}|\" + {3}); }}"; // ASPxCallback, key, fieldName, value
        public MultiRowEditASPxGridListEditor(IModelListView model)
            : base(model) { }
        ASPxCallback callback;
        protected override object CreateControlsCore()
        {
            Panel panel = new Panel();
            callback = new ASPxCallback();
            callback.ID = ObjectTypeInfo.Type.Name + "aspxCallback1";
            callback.ClientInstanceName = ObjectTypeInfo.Type.Name + "_callback1";
            callback.Callback += new CallbackEventHandler(callback_Callback);
            panel.Controls.Add(callback);
            ASPxGridView grid = (ASPxGridView)base.CreateControlsCore();
            grid.HtmlDataCellPrepared += new ASPxGridViewTableDataCellEventHandler(grid_HtmlDataCellPrepared);
            panel.Controls.Add(grid);
            return panel;
        }
        
        void grid_HtmlDataCellPrepared(object sender, ASPxGridViewTableDataCellEventArgs e)
        {
            if (e.DataColumn is GridViewDataColumnWithInfo && IsColumnSupported(((GridViewDataColumnWithInfo)e.DataColumn).Model))
            {
                e.Cell.Attributes["onclick"] = RenderHelper.EventCancelBubbleCommand;
            }
        }

        protected override ITemplate CreateDataItemTemplate(IModelColumn columnInfo)
        {
            if (IsColumnSupported(columnInfo))
            {
                EditModeDataItemTemplate editModeTemplate = (EditModeDataItemTemplate)CreateDefaultColumnTemplate(columnInfo, this, ViewEditMode.Edit);
                editModeTemplate.PropertyEditor.ImmediatePostData = false;
                editModeTemplate.CustomCreateCellControl += new EventHandler<DevExpress.ExpressApp.Web.Editors.CustomCreateCellControlEventArgs>(editModeTemplate_CustomCreateCellControl);
                return editModeTemplate;
            }
            else
            {
                return base.CreateDataItemTemplate(columnInfo);
            }
        }
        
        void editModeTemplate_CustomCreateCellControl(object sender, DevExpress.ExpressApp.Web.Editors.CustomCreateCellControlEventArgs e)
        {
            if (e.PropertyEditor.Editor is ASPxWebControl)
            {
                e.PropertyEditor.Editor.Init += new EventHandler((s, args) => Editor_Init(s, args, e.PropertyEditor.Editor));
            }
            else if (e.PropertyEditor is ASPxLookupPropertyEditor)
            {
                ASPxLookupPropertyEditor editor = e.PropertyEditor as ASPxLookupPropertyEditor;
                editor.DropDownEdit.DropDown.Init += new EventHandler((s, args) => Editor_Init(s, args, e.PropertyEditor.Editor));
            }
            
        }

        void Editor_Init(object sender, EventArgs e,WebControl baseEditor)
        {
            ASPxWebControl editor = (ASPxWebControl)sender;
            editor.Init -= new EventHandler((s, args) => Editor_Init(s, args, baseEditor));
            // Uncomment to remove editors borders
            //editor.Border.BorderStyle = BorderStyle.None;
            GridViewDataItemTemplateContainer container = baseEditor.NamingContainer as GridViewDataItemTemplateContainer;
            var columnInfo = container.Column as GridViewDataColumnWithInfo;
            editor.SetClientSideEventHandler("ValueChanged", String.Format(CallbackArgumentFormat,
                callback.ClientInstanceName, container.KeyValue, columnInfo.Model.PropertyName, editor is ASPxDateEdit ? "s.GetText()" : "s.GetValue()"));
        }

        void callback_Callback(object source, DevExpress.Web.ASPxCallback.CallbackEventArgs e)
        {
            String[] p = e.Parameter.Split('|');
            Object key = TypeDescriptor.GetConverter(ObjectTypeInfo.KeyMember.MemberType).ConvertFromString(p[0]);
            IMemberInfo member = ObjectTypeInfo.FindMember(p[1]);
            Object value = null;
            if (typeof(IXPSimpleObject).IsAssignableFrom(member.MemberType))
            {
                Type memberKeyType = XafTypesInfo.Instance.FindTypeInfo(member.MemberType).KeyMember.MemberType;
                int index1 = p[2].LastIndexOf("(");
                int index2 = p[2].LastIndexOf(")");
                if (index1 > 0 && index2 > index1)
                {
                    string memberKeyText = p[2].Substring(index1 + 1, index2 - index1 - 1);
                    value = ObjectSpace.GetObjectByKey(member.MemberType, Convert.ChangeType(memberKeyText, memberKeyType));
                }
            }
            else
            {
                value = TypeDescriptor.GetConverter(member.MemberType).ConvertFromString(p[2]); ;
            }
            object obj = ObjectSpace.GetObjectByKey(ObjectTypeInfo.Type, key);
            member.SetValue(obj, value);
            ObjectSpace.CommitChanges();
        }

        private Type[] supportedPropertyEditorTypes()
        {
            return new Type[]{
                typeof(ASPxStringPropertyEditor),
                typeof(ASPxIntPropertyEditor),
                typeof(ASPxBooleanPropertyEditor),
                typeof(ASPxEnumPropertyEditor),
                typeof(ASPxDateTimePropertyEditor),
                typeof(ASPxLookupPropertyEditor)
            };
        }

        protected virtual bool IsColumnSupported(IModelColumn model)
        {
            if (model.GroupIndex >= 0)
            {
                return false;
            }
            foreach (Type type in supportedPropertyEditorTypes())
            {
                if (type.IsAssignableFrom(model.PropertyEditorType))
                {
                    return true;
                }
            }
            return false;
        }
        // Sorting and grouping are not supported
        protected override ColumnWrapper AddColumnCore(IModelColumn columnInfo)
        {
            ASPxGridViewColumnWrapper columnWrapper = (ASPxGridViewColumnWrapper)base.AddColumnCore(columnInfo);
            if (IsColumnSupported(columnWrapper.Column.Model))
            {
                columnWrapper.Column.Settings.AllowSort = DevExpress.Utils.DefaultBoolean.False;
                columnWrapper.Column.Settings.AllowGroup = DevExpress.Utils.DefaultBoolean.False;
            }
            return columnWrapper;
        }
    }
}

Added By: Anatol (DevExpress Support) at: 1/31/2014 12:04:45 AM    

Thank you for sharing your code. It looks good. I hope it will be useful for others.

Added By: Apostolis Bekiaris (DevExpress) at: 2/17/2014 7:12:23 AM    

Added in eXpandFramework 13.2.7.4

Added By: HEUNGGI LEE at: 6/4/2014 6:10:47 AM    

Hi,
Is it possible to set width length on each column in GridView? It is ugly...especially Character field grid width is too narrow ..

Added By: Anatol (DevExpress Support) at: 6/5/2014 7:42:58 AM    Yes, this is possible - see Adjust column width in listviews on the Web.Added By: HEUNGGI LEE at: 6/18/2014 9:48:18 PM    

Hi PHN,
I tried with your code but list grid view does not show correctly row items. Last row has same pointer with before last row item.

Added By: HEUNGGI LEE at: 12/28/2014 2:51:20 AM    

Hi,
this code does not work in 14.2.....

Added By: Anatol (DevExpress Support) at: 12/29/2014 6:10:51 AM    

Thank you for your report. It is necessary to turn on Data Item Templates in MultiEditASPxGridListEditor using the UseASPxGridViewDataSpecificColumns property, since they are disabled in version 14.2 by default. I have updated the example.

Added By: Anatol (DevExpress Support) at: 2/3/2015 8:50:08 AM    I have found that this quick fix was insufficient to make this example work correctly in version 14.2. I have replaced it with another fix. A new version is already available.Added By: Warren Connors 4 at: 4/3/2015 12:31:48 PM    

Would it be possible for you guys to update your example runner with a version that shows the date picker and dropdownlist functionality? That would solve 99% of customer needs (as it would solve my current requirement).

Added By: Dennis (DevExpress Support) at: 4/6/2015 3:05:32 AM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T227338: Example Runner: update with a version that shows the date picker and dropdownlist functionality. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.


Viewing all articles
Browse latest Browse all 7205

Trending Articles



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