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

ASPxTreeList - How to get node level on client-side events using HTML attributes


ASPxTreeList: How to Get Node Level on Client-Side Events

$
0
0

ASPxTreeList does not provide a method to determine the node level on the client side. This example demonstrates how to use the ASPxTreeList JSProperties to create this functionality.

In this example, ASPxTreeList ClientSide Event “NodeClick” is handled to redirect the page if a level-2 node is clicked. The new page shows the NodeKey of the node that is clicked.

See also:
ASPxTreeList - How to get node level on client-side events using HTML attributes

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

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.

XL Export API - Examples

$
0
0

This example demonstrates how to use the XL Export API to create spreadsheet files in XLSX, XLS and CSV formats.

This project introduces API properties and methods used to perform the following operations:
- Create a workbook, worksheets, rows, columns and particular cells
- Apply predefined, themed and custom formatting to worksheet cells
- Apply conditional formatting rules
- Enable filtering and group data
- Apply data validation rules
- Assign formulas to worksheet cells
- Specify page settings
- Specify print options
- Insert pictures
- Insert hyperlinks
- Specify document properties
 

ASPxGridView - How to upload files in Edit mode and save them in a binary column

How to bind the SchedulerControl to a collection of custom objects

$
0
0

This example illustrates how you can bind the XtraScheduler to a collection of custom business objects. To accomplish this task, you should have two collections - one for appointments, another for resources. The appointment collection should implement the IBindingList interface. You can implement this interface manually in your custom collection, but we recommend you use the System.ComponentModel.BindingList<T> collection.
Additionally, your business object should have properties suitable for mapping to the corresponding properties of XtraScheduler's appointments and resources.

Question Comments

Added By: Pete R at: 4/23/2013 5:16:30 PM    

Hello,

This sample uses old technology and is needlessly confusing. It is not necessary to manually implement the IBindingList interface. One can use the BindingList<T> class along with a BindingSource. For example:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraScheduler;
using System.Linq;

namespace CustomObjectsBinding {
    public partial class Form1 : Form {
        public static Random RandomInstance = new Random();

        private BindingList<CustomResource> m_customResourceBindingList = new BindingList<CustomResource>();
        private BindingSource m_customResourceBindingSource = new BindingSource();
        private BindingList<CustomAppointment> m_customAppointmentBindingList = new BindingList<CustomAppointment>();
        private BindingSource m_customAppointmentBindingSource = new BindingSource();

        public Form1() {
            InitializeComponent();
            schedulerStorage1.Resources.ColorSaving = ColorSavingType.Color;

        }

        private void Form1_Load(object sender, EventArgs e) {
            InitResources();
            InitAppointments();
            schedulerControl1.Start = DateTime.Now;
            UpdateControls();
        }

       private void InitResources() {
            ResourceMappingInfo mappings = this.schedulerStorage1.Resources.Mappings;
            mappings.Id = "ResID";
            mappings.Color = "ResColor";
            mappings.Caption = "Name";

            m_customResourceBindingList.Add(CreateCustomResource(1, "Max Fowler", Color.PowderBlue));
            m_customResourceBindingList.Add(CreateCustomResource(2, "Nancy Drewmore", Color.PaleVioletRed));
            m_customResourceBindingList.Add(CreateCustomResource(3, "Pak Jang", Color.PeachPuff));

            m_customResourceBindingSource.DataSource = m_customResourceBindingList;
            this.schedulerStorage1.Resources.DataSource = m_customResourceBindingSource;

        }

        private CustomResource CreateCustomResource(int res_id, string caption, Color ResColor) {
            CustomResource cr = new CustomResource();
            cr.ResID = res_id;
            cr.Name = caption;
            cr.ResColor = ResColor;
            return cr;
        }

        private void InitAppointments() {
            AppointmentMappingInfo mappings = this.schedulerStorage1.Appointments.Mappings;
            mappings.Start = "StartTime";
            mappings.End = "EndTime";
            mappings.Subject = "Subject";
            mappings.AllDay = "AllDay";
            mappings.Description = "Description";
            mappings.Label = "Label";
            mappings.Location = "Location";
            mappings.RecurrenceInfo = "RecurrenceInfo";
            mappings.ReminderInfo = "ReminderInfo";
            mappings.ResourceId = "OwnerId";
            mappings.Status = "Status";
            mappings.Type = "EventType";

            List<CustomAppointment> appointmentList = new List<CustomAppointment>();
            GenerateEvents(appointmentList);

            m_customAppointmentBindingList = new BindingList<CustomAppointment>(appointmentList);
            m_customAppointmentBindingSource.DataSource = m_customAppointmentBindingList;

            this.schedulerStorage1.Appointments.DataSource = m_customAppointmentBindingSource;

        }

       private void GenerateEvents(List<CustomAppointment> eventList) {
            int count = schedulerStorage1.Resources.Count;
            for (int i = 0; i < count; i++) {
                Resource resource = schedulerStorage1.Resources[i];
                string subjPrefix = resource.Caption + "'s ";
                eventList.Add(CreateEvent(subjPrefix + "meeting", resource.Id, 2, 5));
                eventList.Add(CreateEvent(subjPrefix + "travel", resource.Id, 3, 6));
                eventList.Add(CreateEvent(subjPrefix + "phone call", resource.Id, 0, 10));
            }
        }

       private CustomAppointment CreateEvent(string subject, object resourceId, int status, int label) {
            CustomAppointment apt = new CustomAppointment();
            apt.Subject = subject;
            apt.OwnerId = resourceId;
            Random rnd = RandomInstance;
            int rangeInMinutes = 60 * 24;
            apt.StartTime = DateTime.Today + TimeSpan.FromMinutes(rnd.Next(0, rangeInMinutes));
            apt.EndTime = apt.StartTime + TimeSpan.FromMinutes(rnd.Next(0, rangeInMinutes / 4));
            apt.Status = status;
            apt.Label = label;
            return apt;
        }

        private void UpdateControls() {
            this.radioGroup1.EditValue = (int)schedulerControl1.GroupType;
        }

        private void radioGroup1_SelectedIndexChanged(object sender, EventArgs e) {
            schedulerControl1.GroupType = (SchedulerGroupType)radioGroup1.EditValue;
        }

    }
}

Then one can use LINQ to Objects and do things like:

            List<CustomAppointment> travelList = m_customAppointmentBindingList.Where(x => x.Subject.Contains("travel")).ToList();
            
etc. Without the need to implement the binding interfaces, the CustomObjects.cs file can be reduced to:

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Collections;
using System.Drawing;

namespace CustomObjectsBinding {

    public class CustomAppointment
    {
        private DateTime m_Start;
        private DateTime m_End;
        private string m_Subject;
        private int m_Status;
        private string m_Description;
        private long m_Label;
        private string m_Location;
        private bool m_Allday;
        private int m_EventType;
        private string m_RecurrenceInfo;
        private string m_ReminderInfo;
        private object m_OwnerId;

        public DateTime StartTime { get { return m_Start; } set { m_Start = value; } }
        public DateTime EndTime { get { return m_End; } set { m_End = value; } }
        public string Subject { get { return m_Subject; } set { m_Subject = value; } }
        public int Status { get { return m_Status; } set { m_Status = value; } }
        public string Description { get { return m_Description; } set { m_Description = value; } }
        public long Label { get { return m_Label; } set { m_Label = value; } }
        public string Location { get { return m_Location; } set { m_Location = value; } }
        public bool AllDay { get { return m_Allday; } set { m_Allday = value; } }
        public int EventType { get { return m_EventType; } set { m_EventType = value; } }
        public string RecurrenceInfo { get { return m_RecurrenceInfo; } set { m_RecurrenceInfo = value; } }
        public string ReminderInfo { get { return m_ReminderInfo; } set { m_ReminderInfo = value; } }
        public object OwnerId { get { return m_OwnerId; } set { m_OwnerId = value; } }

        public CustomAppointment()
        {
        }
    }

    public class CustomResource {
        private string m_name;
        private int m_res_id;
        private Color m_res_color;

        public string Name { get { return m_name; } set { m_name = value; } }
        public int ResID { get { return m_res_id; } set { m_res_id = value; } }
        public Color ResColor { get { return m_res_color; } set { m_res_color = value; } }

        public CustomResource()
        {
        }
    }

}

Please verify.

Added By: Tejaswi Rana at: 10/24/2013 3:41:59 PM    

What is the bare minimum mapping details necessary to display an appointment? For example, I have an object that only has the properties StartTime, EndTime, Description & Type. I have not linked any resources to any of these objects. And I am using a bindingList<of thisClass>. This is in version 8.3. I don't see any output.

Added By: Tejaswi Rana at: 10/24/2013 6:56:08 PM    

I will answer the above myself: This works in version 8.3. Actually the comment above helped a lot :).
Also, there is no need to have resources if you're including them within something like "description" of the appointment itself.
You can have as many mappings as you want to send. The only thing to be careful about is if you have a mapping and don't send data or proper data type.

Added By: Louis Kleiman 2 at: 9/2/2015 5:34:09 AM    

Can you add to this example to show how to add appointments after the initial load?  I am using a custom dialog and adding my objects to my source binding list, but they do not appear until I completely reload my gantt chart.

Added By: Andrey (DevExpress Support) at: 9/2/2015 8:18:38 AM    

Hello,

To process your recent post more efficiently, I created a separate ticket on your behalf: T285177: How to refresh the scheduler on adding an appointment in the E750 example. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

How to reorder ASPxGridView rows using buttons or drag-and-drop

$
0
0

This example demonstrates how to move ASPxGridView rows using buttons or jQuery Drag&Drop.


To keep the order of rows, it is necessary to set up an extra column to store row order indexes. Then, sort ASPxGridView by this column and deny sorting by other columns. This example stores this information in the unbound column and additionally puts a dictionary "row key = row index" to the session. We have implemented this approach only for demo purposes. You can store this information in your DataSource.

Updated:

We updated an example for v.14.2 to show how to save order information to a database and tune the ASPxGridView drag and drop appearance using the UI Draggable and Droppable plug-ins. If you need to check the unbound column  implementation, choose the second item in the version build combo box. 

 

See also:
T191258 - How to reorder GridView rows using buttons or drag-and-drop

E1810: How to use jQuery to drag and drop items from one ASPxGridView to another

E3850: How to reorder ASPxTreeList sibling nodes, using buttons or drag-and-drop
E4299: How to move up or down a line a row of ASPxGridView by using external buttons

Question Comments

Added By: Hiren Joshi (Venture) at: 8/20/2013 3:03:21 PM    

Hello,

I have seen your example however I have a question from user view point. Once you start to drag a row button you don't have any way to tell which row you are dragging. So unless you remember the row to started with it will be diffcult for users to use this practically. Do you have a way to drag the entire row or have a button with some text to identify the row you are dragging? Please let me know if this is possible.

Added By: Jacob Blumberg at: 8/27/2013 4:05:00 PM    

I agree, that is what I am looking for too.

Added By: Hiren Joshi (Venture) at: 9/11/2013 10:54:22 AM    

I was able to use the link tag <a href=""><%#Eval("YourData")%></a> instead of the image; in order to over come the problem of knowing which row is being dragged. So now when I drag the row I can see the text that I am dragging.

Added By: Wouter Stichelbout at: 2/11/2014 7:54:23 AM    

I there an MVC equivalent?

Added By: Vasily (DevExpress Support) at: 2/11/2014 9:48:17 AM    

Hi Wouter,

I have extracted your question to a separate ticket created on your behalf: Q466606: GridView - How to reorder GridView rows using buttons or drag-and-drop.
Your time and cooperation are appreciated.

Added By: Walter Rijk at: 6/23/2014 1:45:25 AM    

Hello,

This approach much more resembles the way Telerik has implemented row dragging and dropping:

       function InitalizejQuery() {
           var openhand = "url(https://mail.google.com/mail/images/2/openhand.cur), move";
           var closedhand = "url(https://mail.google.com/mail/images/2/closedhand.cur), move";

           $('.dxgvDataRow, .dxgvFocusedRow').each(function () {
               $(this).css({ "cursor": openhand });
           });
           $('.dxgvDataRow, .dxgvFocusedRow').draggable({
               helper: function () {
                   var result = $("<table class='dxgvTable' cellspacing='0' cellpadding='0' style='opacity:0.7;background-color:#dddddd;'>").append($(this).clone()).append($("</table>"));
                   $("td", this).each(function (index) {
                       $("td", result).eq(index).css({ 'width': $(this).width() });
                   });
                   return result;
               },
               axis: "y",
               start: function (event, ui) {
                   $("tr", $(this).parent()).each(function (index) {
                       $(this).css({ "cursor": closedhand });
                       $(this).removeClass('dxgvFocusedRow'); // this is the same as removing the focussedrowindex
                       $(this).addClass('dxgvDataRow');
                   });
                   $(this).addClass('dxgvFocusedRow');
               },
               stop: function (event, ui) {
                   $(this).css({ "cursor": openhand });
               }
           });
           $('.dxgvDataRow, .dxgvFocusedRow').droppable({
               drop: function (event, ui) {
                   var draggingRowKey = ui.draggable.find("input[type='hidden']").val();
                   var targetRowKey = $(this).find("input[type='hidden']").val();
                   gridView.PerformCallback("DRAGROW|" + draggingRowKey + '|' + targetRowKey);
               }
               , over: function (event, ui) {
                   var targetRowKey = $(this).find("input[type='hidden']").val();
                   var rowindex = gridView.keys.indexOf(targetRowKey);
                   window.setTimeout(function () { gridView.MakeRowVisibleNew(rowindex); }, 100);
                   $(this).addClass('borderClass');
               }
               , out: function (event, ui) {
                   $(this).removeClass('borderClass');
               }
           });
       }

Best Regards,
Ernstjan Freriks

Added By: Kchouk at: 12/8/2014 2:00:35 PM    

I am having difficulties figuring out how to actually use a field from the datasource to save the sorting order. Any help will be appreciated.

Added By: Artem (DevExpress Support) at: 12/9/2014 12:17:45 AM    

Hello,

To process your post more efficiently, I created a separate ticket on your behalf: T184636: ASPxGridView - How to save sort order to a database using approach from the E4582. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

Added By: Gregory Lange 1 at: 4/9/2015 12:28:22 PM    

Just a suggestion you should also make these for where people load data via datasource in the code behind because trying to translate this sometime to that things get messed up.

Added By: Anthony (DevExpress Support) at: 4/9/2015 1:07:37 PM    

Hi Gregory,

You are always welcome to create a support ticket if you have difficulties in implementing approaches from our examples.

Added By: Michael Herron at: 9/2/2015 9:28:02 AM    

This example does not work if used within a MasterPage. Has anyone tried this?

Added By: Artem (DevExpress Support) at: 9/2/2015 1:14:20 PM    

Hello Michael,

To process your recent post more efficiently, I created a separate ticket on your behalf: T285292: E4582 doesn't work if ASPxGridView in on a MasterPage. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

GridView - How to implement data editing with hidden column

$
0
0

Problem:

I need to hide some columns in the GridView because they are utilized for internal purpose (e.g., rowversion column). At the same time, it is necessary to have these column values in the update action method specified via the MVCxGridViewEditingSettings.UpdateRowRouteValues Property. Currently, the corresponding values are empty.

Solution:

This issue occurs because the generated HTML does not contain INPUT fields that correspond to hidden columns. For this reason, when data is posted to the server, the corresponding model fields are left empty (the model binding mechanism cannot find appropriate values for these fields). To solve this problem, you can use the approach from the Passing Values to Controller Action Through Callbacks help section to forcibly pass the required values to the update action method. In addition to the MVCxClientGridView.BeginCallback Event, you need to handle the GridViewSettings.CustomJSProperties Event to pass the currently edited row values to the client side.

Note:

If it is OK for you to show the caption and editor of the hidden column in the Edit Form, you can use a much simpler solution. Just set the GridColumnEditFormSettings.Visible property to true. This approach might be useful when you are hiding columns via the Customization Window.


How to define a custom IConnectionStorageService in DashboardDesigner Wizard to filter out unnecessary connections from an app.config file  

$
0
0

This example demonstrates how to implement a custom IConnectionStorageService and use it instead of the default one in the data source wizard. This service implementation allows only getting connection parameters from the DashboardDesigner.CustomDataConnection collection. To load the custom service instead of the default one, execute the following code:

[C#]
dashboardDesigner1.ServiceContainer.RemoveService(typeof(IConnectionStorageService));dashboardDesigner1.ServiceContainer.AddService(typeof(IConnectionStorageService),newCustomConnectionStorageService(dashboardDesigner1));

WinForms End-User Report Designer - How to hide a property in the Properties window

WPF Report Designer - How to hide a property in the Properties window

$
0
0
This example demonstrates how to hide the "DataSource", "DataMember", and "DataAdapter" properties in the End-User Report Designer's Properties window.


First, get the Property Grid from the visual tree. I completed this by using the LayoutTreeHelper class. Then, get a property definition instance from the PropertyGridControl.PropertyDefinitions collection and set PropertyDefinitionBase.Visibility to Collapsed to hide a property.

Here are some points regarding how to get a property from the PropertyGridControl.PropertyDefinitions collection.
In the Resources.xaml file, there is a template used by the End-User Designer's Property Grid. Some of properties are determined by the PropertyDefinitionBase.Path property (for instance, the "DataSource" and "PrinterName" properties).
To hide them, compare the PropertyDefinitionBase.Path property value with the string value (e.g. "DataSource") to get a property object from PropertyGridControl.PropertyDefinitions.

Other properties are determined by the type. To hide them, create a brand new PropertyDefinitionBase object (set up its Path as required) and add it to the PropertyGridControl.PropertyDefinitions.

WinForms: WinForms End-User Report Designer - How to hide a property in the Properties window

How to allow an end-user to move the rows in a grid up and down if the grid is bound to a DataTable

$
0
0

This example demonstrates how to swap two rows to move a specific row up or down

Question Comments

Added By: dsk96m at: 9/19/2013 9:07:54 AM    

This code is great, but does not work if you delete a row. If I have 6 items in the list and I delete item 2, this code doesnt work. How do we make it work in that case. Also, the ordering doesnt work, the numbers change to like 10.5, etc.

Added By: dsk96m at: 9/19/2013 9:09:05 AM    

Nevermind the second part of that. But how do we make this work so i can delete a row.

Added By: Faizan Mubasher at: 9/3/2015 12:37:12 AM    

There is a problem! There are rows with dim and visible Expand buttons. Like, if there exist child row then expand button will be proper visible but dim otherwise just like normal grid behavior. But when rows are swapped, expand buttons doesn't change their state accordingly which is wrong and undesirable. Can you sort out the issue?

Added By: Alexey Z (DevExpress Support) at: 9/3/2015 12:55:13 AM    Hello,

I see that you have posted the same comment in the How to allow an end-user to move the rows in a grid up and down if the grid is bound to a DataTable article. So, I have created a new The E719 example does not work with Detail view thread on your behalf to process your recent post more efficiently.Added By: Faizan Mubasher at: 9/3/2015 1:03:24 AM    

Another issue! What if the Row is expanded and we swap them?

Added By: Alexey Z (DevExpress Support) at: 9/3/2015 1:58:57 AM    Hello,

Let's continue our discussion in the The E719 example does not work with Detail view thread.

ASPxCardView - How to create a custom command button

How to access and remove rows by using a custom cell's context menu.

$
0
0

This example shows how to access and remove rows by using a custom cell's context menu.

WPF Report Designer - How to customize the reporting popup menu


WinForms End-User Designer - How to customize the popup-menu

$
0
0

This sample illustrates how you can customize the popup-menu that is shown by the right-click onto the Design panel of the Report Designer.
In particular, it illustrates the process of adding the option of showing and hiding the Designer grid.

WPF: WPF Report Designer - How to customize the reporting popup menu

Question Comments

Added By: Marco Zierl 1 at: 5/21/2013 3:13:23 AM    

Hi,

I want to use this approach to remove the "Edit Parameters ..." command from the pop-up menu in the field list. What I came up with looks like this:

public void ProcessMenuItems(MenuKind menuKind, MenuItemDescriptionCollection items)
{
            if (menuKind == MenuKind.FieldList)
            {
                CommandID removeCommand = null;
                foreach (var item in items)
                {
                    if (item.CommandID != null && item.CommandID.ID == 6) removeCommand = item.CommandID;
                }
                if (removeCommand != null) items.Remove(removeCommand);
            }

}

Obviously, hard-coding the command ID (6) is not a good solution, but I could not find the corresponding Enum value. Can you help me here?

Marco

Added By: Uwe Philipps at: 10/1/2013 3:33:28 AM    

When using this example I only see the custom menu items on the first time the designer is shown.
When opening the designer again, ProcessMenuItems() is not called and the custom menu items are not shown.

I'm using Visual Studio 2010 and DevExpress Reporting V13.1.7

Added By: Dmitry Tok (DevExpress Support) at: 2/2/2015 12:38:35 AM    

Hello Uwe,

To process your recent post more efficiently, I created a separate ticket on your behalf: T203628: An issue with the E4343 Code Example. This ticket is currently in our processing queue. Our team will address it as soon as we have any updates.

ASPxGridView - How to adjust Edit Form layout using the EditFormLayoutProperties property

$
0
0
In this example, the Edit Form layout is customized by using the EditFormLayoutProperties property. The CategoryID column's editor is set to ASPxComboBox. The ProductID column's editor is displayed only when editing an existing row. All editor locations are customized with the ColSpan and RowSpan properties. The ProductID field is marked with an asterisk like the required field.

How to implement custom behavior for an expand button of group rows

$
0
0

This example demonstrates how to expand child rows recursively when a parent group row is expanded. This feature is implemented by handling a client-side RowExpanding event and sending a custom callback.

Question Comments

Added By: Jagan Yammada at: 9/3/2015 11:42:32 AM    

What this does for me is that it expands  the list recursively but then contracts to the first level again in a flash. I tried e.Cancel = true; but that did not help. Can you please help>?

Thaks.

GridView - How to create a custom "Select Page Size" element with the "Show All Records" feature

$
0
0

Problem:
I wish to implement custom paging elements with the capability to show all records.

Solution:
Generally, it is possible to override the template for the Pager area using the GridViewSettings.SetPagerBarTemplateContent(Action`1) method. However, in this scenario the entire area with your custom template will be hidden once you set the ASPxGridViewPagerSettings.Mode property to the ShowAllRecords value. This is expected behavior. To overcome it, you can leave the default page UI and add custom pager elements to the  Footer area by overriding its template instead using the GridViewSettings.SetFooterRowTemplateContent(Action`1) method.

Note 1: Currently, there is no capability to replicate the default UI of the GridView's specific visual element within a template of this element. We have discussed this topic in the S37728: Add the GridViewTemplateReplacement extension ticket.

Note 2: If necessary, you can display the "Show All Records" item in the "Select Page Size" element of the built-in pager without implementing custom templates:

[C#]
@Html.DevExpress().GridView(settings=>{settings.Name="GridView";settings.SettingsPager.PageSizeItemSettings.Visible=true;settings.SettingsPager.PageSizeItemSettings.ShowAllItem=true;...
[VB.NET]
@Html.DevExpress().GridView( _Sub(settings) settings.Name = "GridView" settings.SettingsPager.PageSizeItemSettings.Visible = True settings.SettingsPager.PageSizeItemSettings.ShowAllItem = True ...

How to customize the underlying database provider options and data access behavior in XAF

$
0
0

IMPORTANT NOTE

This article describes some advanced customization techniques and low-level entities of the framework with regard to data access, which may be required in complex scenarios only.
So, if you just want to change the connection string, e.g. to use the Oracle instead of the Microsoft SQL Server database, then you would better refer to the Connect an XAF Application to a Database Provider article and documentation on your database provider instead. The XAF integration of supported ORM libraries is also described in the Business Model Design section of the framework's documentation.


Introducing IObjectSpaceProvider and IObjectSpace
XAF accesses data from a data store through special abstractions called - IObjectSpaceProvider and IObjectSpace.
The IObjectSpace is an abstraction above the ORM-specific database context (e.g., the DBContext used in Entity Framework or the Session in XPO) allowing you to query or modify data.
The IObjectSpaceProvider is a provider/creator of IObjectSpace entities, which also manages which business types these IObjectSpace are supposed to work with, how to set up the underlying connection to the database, create and update it and other low level data access options.



An XafApplication can use one or several IObjectSpaceProvider objects at the same time, and you can access this information through the XafApplication.ObjectSpaceProvder or XafApplication.ObjectSpaceProviders properties. Check out these help links to learn more on how to plug in custom IObjectSpaceProvider objects a well.

There are several built-in implementations of the IObjectSpaceProvider and IObjectSpace interfaces in our framework, which are usually specific to a target ORM (Entity Framework or XPO). I suggest you check out the source code of the default framework classes to better understand the role of the IObjectSpaceProvider:

...\DevExpress.ExpressApp.Xpo\XPObjectSpaceProvider.cs
...\DevExpress.ExpressApp.EF\EFObjectSpaceProvider.cs 

Typical customization considerations
You may want to provide a fully custom IObjectSpaceProvider implementation or inherit from the built-in implementors when you want to customize how data access is performed for a chosen ORM.
Below is a list of typical scenarios where a custom IObjectSpaceProvider may be required:

1. How to use XPO caching in XAF 
2. How to prevent altering the legacy database schema when creating an XAF application 
3. How to connect to remote data store and configure WCF end point programmatically 
4. How do I change the default schema in the database
5. How to use a custom ObjectSpace throughout the application by handling the CreateCustomObjectSpaceProvider event? 

In most cases, it is not required to implement the IObjectSpaceProvider interface from scratch since you can inherit from existing implementors or customize/just their parts.


XPO-specific customizations

1. Implementing IXpoDataStoreProvider

For instance, in XPO one of such replaceable parts is the IXpoDataStoreProvider interface, which enables you to provide a custom or configured IDataStore object, which is used for underlying data access with this ORM:

[C#]
publicinterfaceIXpoDataStoreProvider{IDataStoreCreateWorkingStore(outIDisposable[]disposableObjects);IDataStoreCreateUpdatingStore(outIDisposable[]disposableObjects);stringConnectionString{get;}}

 

In its turn, XAF provides several ready to use implementations of this interface for most popular scenarios: 

1. ConnectionDataStoreProvider - can provide IDataStore by the IDbConnection object;

2. ConnectionStringDataStoreProvider - can provide IDataStore by just connecting string information;

3. MemoryDataStoreProvider - DataSet based in-memory IDataStore providers.


Technically, such an IXpoDataStoreProvider part is passed into the XPObjectSpaceProvider constructor as a parameter, which means that you can just customize it instead of re-implementing the whole XPObjectSpaceProvider logic.

Refer to the ...\DevExpress.ExpressApp.Xpo\XPObjectSpaceProvider.cs file within the XAF source code to better understand the role of this part.

2. Overriding XPO connection or database providers

To learn more on this approach, check out the Database Systems Supported by XPO help topic and How to create a custom XPO connection provider and then use it in an XAF application article in particular.

 

To learn more on customizing data access settings for XPO, please refer to the corresponding product documentation: Data Access Layer.

Viewing all 7205 articles
Browse latest View live


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