Back to Devexpress

Deferred Load

windowsforms-11619-controls-and-libraries-application-ui-manager-deferred-load-deferred-load.md

latest16.3 KB
Original Source

Deferred Load

  • Apr 19, 2024
  • 8 minutes to read

If your view contains many documents, you may want to use the deferred load feature. The main idea of the deferred load is that you initially create “empty” documents and provide content for them later, via an event that fires when an empty document is about to be displayed. The deferred load approach allows you to significantly reduce the application start-up initialization time, but navigation through documents will be a little slower compared to the direct content loading approach via the BaseView.AddDocument method.

Documents must be empty (i.e., have no content) to trigger the deferred load mechanism.

At runtime, you can create empty documents via the BaseView.AddDocument method overload without the Control parameter. At design time, you can create empty documents via the Document Manager Designer. Switch to the ‘Documents’ tab and add documents via the “Add New Document” button.

To specify the content (of any control) for an empty document, handle the BaseView.QueryControl event. This event is the first one triggered by the deferred load mechanism when an empty document is about to be displayed. It fires on application start-up (when displaying the first “empty” document), and each time an end-user activates another “empty” document (for instance, by clicking a tab header in the TabbedView). To set the content for the document, assign a control to the event’s Control parameter, as shown below.

csharp
private void windowsUIView1_QueryControl(object sender, DevExpress.XtraBars.Docking2010.Views.QueryControlEventArgs e) {
    if(e.Document == document1)
         e.Control = new UserControl1();
    if(e.Document == document2)
         e.Control = new UserControl2();
}
vb
Private Sub windowsUIView1_QueryControl(sender As Object, e As DevExpress.XtraBars.Docking2010.Views.QueryControlEventArgs)
    If e.Document = document1 Then
        e.Control = New UserControl1()
    End If
    If e.Document = document2 Then
        e.Control = New UserControl2()
    End If
End Sub

Note

Alternatively, you can assign a control to the BaseDocument.ControlType property.

After a document’s content has been displayed, the BaseView.ControlShown event fires.

By default, the deferred load mechanism persists the document content when the document is unselected. For instance, when switching from one tab to another in the TabbedView, the previously activated tab’s contents are not destroyed by default. In the NativeMdiView, document content is never destroyed.

If you want to unbind a document’s content, handle the BaseView.ControlReleasing event and set the event’s KeepControl parameter to false. For this document, the BaseView.QueryControl event will repeatedly fire when the document is activated again. By default, unbound content is automatically destroyed.

When handling the BaseView.ControlReleasing event, you also have the option to unbind a document from its content without destroying the content itself so you can pass it to another document. This can be accomplished by setting the event’s KeepControl and DisposeControl parameters to false.

After a control has been unbound from its parent document, the BaseView.ControlReleased event is raised.

The diagram below demonstrates this event sequence.

The following code from DevExpress BarTutorials (‘Deferred Load’ demo) illustrates how to use the BaseView.QueryControl and BaseView.ControlReleasing events:

csharp
public partial class DocumentManagerDeferredLoadDocuments : TutorialControl {
    public DocumentManagerDeferredLoadDocuments() {
        InitializeComponent();
    }
    int i = 0;
    //A string array used to fill document content
    string[] texts = new string[]{ 
        "Vestibulum sem nunc, cursus sit amet placerat id, scelerisque at tortor. Nullam sit amet felis eros, ac imperdiet quam. Aliquam eu ipsum dui.",
        "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur sit amet sapien metus, eget pharetra velit.",
        "Duis sagittis iaculis nisl, sit amet ultricies lectus porttitor nec. Suspendisse id venenatis sem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.",
        "Aliquam erat volutpat. Ut sit amet purus. Nullam a lectus. Duis in elit. Ut nonummy est pellentesque eros. Sed ultrices convallis nulla. Phasellus urna lorem, mattis a, luctus congue, dictum in, nunc."
        };
    //Creates a label, sets this text via the GetText function, places the label onto a Panel object and sets this panel as the document content.
    void tabbedView_QueryControl(object sender, QueryControlEventArgs e) {
        Panel child = new Panel();
        child.Padding = new Padding(16);
        LabelControl label = new LabelControl();
        label.Text = GetText(i);
        label.AutoSizeMode = LabelAutoSizeMode.Vertical;
        child.Controls.Add(label);
        label.Dock = DockStyle.Fill;
        e.Control = child;
        i++;
        }
    //Gets a specific string from the 'texts' array. The Sleep method emulates the time required to load content for complex documents.
    string GetText(int i) {
        System.Threading.Thread.Sleep(1000);
        return string.Format("{0} {1}", texts[i % texts.Length], texts[(i + 2) % texts.Length]);
        }
    //Prevents unselected documents from being destroyed.
    void tabbedView_ControlReleasing(object sender, ControlReleasingEventArgs e) {
        e.Cancel = true;
        //or
        //e.KeepControl = true;
    }
}
vb
Public Partial Class DocumentManagerDeferredLoadDocuments
    Inherits TutorialControl
    Public Sub New()
        InitializeComponent()
    End Sub
    Private i As Integer = 0
    'A string array used to fill document content
    Private texts As String() = New String(){ "Vestibulum sem nunc, cursus sit amet placerat id, scelerisque at tortor. Nullam sit amet felis eros, ac imperdiet quam. Aliquam eu ipsum dui.", "Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Curabitur sit amet sapien metus, eget pharetra velit.", "Duis sagittis iaculis nisl, sit amet ultricies lectus porttitor nec. Suspendisse id venenatis sem. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.", "Aliquam erat volutpat. Ut sit amet purus. Nullam a lectus. Duis in elit. Ut nonummy est pellentesque eros. Sed ultrices convallis nulla. Phasellus urna lorem, mattis a, luctus congue, dictum in, nunc." }
    'Creates a label, sets this text via the GetText function, places the label onto a Panel object and sets this panel as the document content.
    Private Sub tabbedView_QueryControl(ByVal sender As Object, ByVal e As QueryControlEventArgs)
        Dim child As Panel = New Panel()
        child.Padding = New Padding(16)
        Dim label As LabelControl = New LabelControl()
        label.Text = GetText(i)
        label.AutoSizeMode = LabelAutoSizeMode.Vertical
        child.Controls.Add(label)
        label.Dock = DockStyle.Fill
        e.Control = child
        i += 1
    End Sub
    'Gets a specific string from the 'texts' array. The Sleep method emulates the time required to load content for complex documents.
    Private Function GetText(ByVal i As Integer) As String
        System.Threading.Thread.Sleep(1000)
        Return String.Format("{0} {1}", texts(i Mod texts.Length), texts((i + 2) Mod texts.Length))
    End Function
    'Prevents unselected documents from being destroyed.
    Private Sub tabbedView_ControlReleasing(ByVal sender As Object, ByVal e As ControlReleasingEventArgs)
        e.Cancel = True
        'or
        'e.KeepControl = True
    End Sub
End Class

When you need to populate multiple similar Documents, you can specify their BaseDocument.Tag property. Then, when handling the QueryControl event, you can check these tags and depending on their values pass a required content to a current Document. The code below illustrates how to pass different detail User Controls depending on the employee department.

csharp
//assign string tags to all documents
document1.Tag = "Developer";
document2.Tag = "Support";
document3.Tag = "TechWriter";
document4.Tag = "QA";
document5.Tag = "HR";

private void tabbedView1_QueryControl(object sender, DevExpress.XtraBars.Docking2010.Views.QueryControlEventArgs e) {
    //check document tags and pick a corresponding User Control for each document
    switch (e.Document.Tag.ToString()) {
        case "Developer":
            e.Control = new developerDetailUserControl();
            break;
        case "Support":
            e.Control = new supportDetailUserControl();
            break;
        case "TechWriter":
            e.Control = new techWriterDetailUserControl();
            break;
        case "QA":
            e.Control = new QADetailUserControl();
            break;
        case "HR":
            e.Control = new HRDetailUserControl();
            break;
    }
}
vb
'assign string tags to all documents
document1.Tag = "Developer"
document2.Tag = "Support"
document3.Tag = "TechWriter"
document4.Tag = "QA"
document5.Tag = "HR"

Private Sub tabbedView1_QueryControl(sender As Object, e As DevExpress.XtraBars.Docking2010.Views.QueryControlEventArgs)
        'check document tags and pick a corresponding User Control for each document
        Select Case e.Document.Tag.ToString()
            e.Control = New developerDetailUserControl()
            Exit Select
        Case "Support"
            e.Control = New supportDetailUserControl()
            Exit Select
        Case "TechWriter"
            e.Control = New techWriterDetailUserControl()
            Exit Select
        Case "QA"
            e.Control = New QADetailUserControl()
            Exit Select
        Case "HR"
            e.Control = New HRDetailUserControl()
            Exit Select
        End Select
End Sub

Navigation through documents can be accompanied by a load indicator (see the figure below). Its availability is specified via the BaseView.UseLoadingIndicator property. You can access a loading indicator’s appearance settings using the BaseView.LoadingIndicatorProperties property.

How to Reuse Controls after a Document is Closed

The following example demonstrates how to cache controls and reuse them after a document is closed:

csharp
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Docking2010.Views;

namespace DXApplication {
    public partial class Form1 : DevExpress.XtraEditors.XtraForm {
        public Form1() {
            InitializeComponent();

            tabbedView1.QueryControl += TabbedView1_QueryControl;
            tabbedView1.ControlReleasing += TabbedView1_ControlReleasing;
        }

        private void TabbedView1_ControlReleasing(object sender, ControlReleasingEventArgs e) {
            e.KeepControl = false;
            e.DisposeControl = false;
        }
        Dictionary<string, Control> cache = new Dictionary<string, Control>();
        private void TabbedView1_QueryControl(object sender, QueryControlEventArgs e) {
            var tag = e.Document.Tag.ToString();
            if(!cache.ContainsKey(tag)) {
                cache.Add(tag, new UserControl1() { BackColor = Color.FromName(tag) });
                Debug.WriteLine("Control created");
            }

            e.Control = cache[tag];
        }

        private void barButtonItem1_ItemClick(object sender, ItemClickEventArgs e) {
            var doc = tabbedView1.AddDocument("Red", "Red");
            doc.Tag = "Red";
        }

        private void barButtonItem2_ItemClick(object sender, ItemClickEventArgs e) {
            var doc = tabbedView1.AddDocument("Green", "Green");
            doc.Tag = "Green";
        }

        private void barButtonItem3_ItemClick(object sender, ItemClickEventArgs e) {
            var doc = tabbedView1.AddDocument("Blue", "Blue");
            doc.Tag = "Blue";
        }
    }
}
vb
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Drawing
Imports System.Windows.Forms
Imports DevExpress.XtraBars
Imports DevExpress.XtraBars.Docking2010.Views

Namespace DXApplication
    Partial Public Class Form1
        Inherits DevExpress.XtraEditors.XtraForm

        Public Sub New()
            InitializeComponent()

            AddHandler tabbedView1.QueryControl, AddressOf TabbedView1_QueryControl
            AddHandler tabbedView1.ControlReleasing, AddressOf TabbedView1_ControlReleasing
        End Sub

        Private Sub TabbedView1_ControlReleasing(ByVal sender As Object, ByVal e As ControlReleasingEventArgs)
            e.KeepControl = False
            e.DisposeControl = False
        End Sub
        Private cache As New Dictionary(Of String, Control)()
        Private Sub TabbedView1_QueryControl(ByVal sender As Object, ByVal e As QueryControlEventArgs)
            Dim tag = e.Document.Tag.ToString()
            If Not cache.ContainsKey(tag) Then
                cache.Add(tag, New UserControl1() With {.BackColor = Color.FromName(tag)})
                Debug.WriteLine("Control created")
            End If

            e.Control = cache(tag)
        End Sub

        Private Sub barButtonItem1_ItemClick(ByVal sender As Object, ByVal e As ItemClickEventArgs)
            Dim doc = tabbedView1.AddDocument("Red", "Red")
            doc.Tag = "Red"
        End Sub

        Private Sub barButtonItem2_ItemClick(ByVal sender As Object, ByVal e As ItemClickEventArgs)
            Dim doc = tabbedView1.AddDocument("Green", "Green")
            doc.Tag = "Green"
        End Sub

        Private Sub barButtonItem3_ItemClick(ByVal sender As Object, ByVal e As ItemClickEventArgs)
            Dim doc = tabbedView1.AddDocument("Blue", "Blue")
            doc.Tag = "Blue"
        End Sub
    End Class
End Namespace

See Also

ControlShown

ControlReleasing

ControlReleased

UseLoadingIndicator

LoadingIndicatorProperties