Search This Blog

Showing posts with label Views. Show all posts
Showing posts with label Views. Show all posts

Wednesday, February 14, 2018

Customization Forms and Model Editor Improvements - XAF v17.2.6

Customizing Views layout, e.g., making certain fields visible, changing their locations is something that XAF developers usually learn and appreciate from day one. That is because you can drastically change the UI of your app by just moving the mouse and without any coding and recompilation, also at runtime. 

The next maintenance release (v17.2.6) should come with a few minor improvements to the customization forms in DetailView, ListView and the Model Editor, which we hope will be welcomed by both developers and end-users as well.


Wednesday, February 7, 2018

No Visual Studio designers for generic ViewController versions

XAF Controllers are technically descendants of the System.ComponentModel.Component class, primarily to be smoothly integrated with the Visual Studio design time features. The standard Component designer does not support generic classes due to a Visual Studio limitation: https://stackoverflow.com/questions/6877217/can-visual-studio-designer-show-classes-inheriting-generic-types 
This is a Microsoft functionality and we cannot do much about it on our side. So, if you have a class like this, and try to double click it or use the Enter key for it in the Solution Explorer, you will receive this error, which is expected here:



This has always caused support calls to us from day one and still causes them today. Check out this support article to learn more about this situation and our previous recommendations.

Starting with v17.2.6, we have removed the visual designer association from the base ViewController<ViewType> and ObjectViewController<ViewType, ObjectType> classes - they will always be opened directly in the Code Editor now. This should work fine in Visual Studio 2015, 2017 and newer versions. This does not work for Visual Studio 2013 and older versions and we decided not to investigate this further, because of the very low usage rate of these IDEs nowadays.



We believe that this new behavior is most expected here and really hope that it will not cause new questions😀. Originally, generic View Controllers were specially designed for users who prefer to do everything manually and want to have a more elegant and compact code. So, opening the Code Editor for such classes is naturally expected. Taking this opportunity, we also improved our online documentation to further promote generic View Controllers, since most of our Support Center answers, demos and docs use this concise code approach anyway.

My team and I are looking forward to hear from you on what you think of the new behavior.

Friday, August 18, 2017

How to: Save and share custom view settings


An often scenario is when an end-user changes certain View settings (columns and editors' layout, filters, etc.) and wants to share these customizations with other users. The XAF core team has prepared an example demonstrating how to allow users to create new View Variants, persist them and load shared variants from the application database.


You can download the example source code and read the detailed description at

Your feedback is needed!
Should you face any issue using this solution or difficulty implementing it in your project, please describe your own scenario of sharing View settings. We will research this information to make the functionality better. 

Thursday, July 27, 2017

Survey (~1min): Default location of the Reset View Settings Action - YOUR FEEDBACK IS NEEDED!!!

This command is provided by the standard ResetViewSettingsController and resets all the user customizations of the View's model. It may be helpful when your client customized a lot and was stuck getting things to normal. Due to this scenario the command is available in the main menu toolbar or ribbon by default (+additionally duplicated in context menu in WinForms).



However, we wanted to hear the XAF community thoughts on this default design after receiving several user requests in this regard (examples: onetwo, three). As of now, we have no easy capability to know real usages and customizations of XAF Actions in end client apps, so we would greatly appreciate it if you participate in this and coming surveys. Thanks for your help in advance.

https://dxsurvey.com/published?id=45965fae-dfc7-48ac-af26-aee17d2c3ec4

In fact, we already asked our user preferences when this feature was in development, but did not receive much feedback back then to hide this command from the main menu by default.

Friday, April 21, 2017

Documentation updates with regard to ways to resize windows in XAF

We have recently updated our online documentation in this regard, so you may be interested to check it out:
    Task-Based Help > How to: Adjust the Size and Style of Pop-up Dialogs (WinForms)
    Task-Based Help > How to: Adjust the Size and Style of Pop-up Dialogs (ASP.NET)

Attentive readers could notice that the PopupWindowShowAction.CustomizePopupWindowParams event arguments now provide the new Size and Maximized properties that can be used to specify the popup window size from a platform-agnostic module in certain cases (check the end of both articles above for more details on the limitations).

Of course, these code solutions can be further improved based on your business requirements. For instance, if you want to provide a developer or application user with the capability to specify sizes in the Model Editor, you can extend required View node types (e.g., IModelView) with the Width and Height attributes in the Application Model and then modify the aforementioned code to read these attributes respectively. Refer to the eXpressApp Framework > Concepts > Application Model > Extend and Customize the Application Model in Code article for more details.


Please tell me about your experience with these solutions or about anything you would love to improve in this regard. Thanks in advance.

FreeImages.com/Carolina Rodríguez

Tuesday, March 7, 2017

How to change an Application Model option globally or for multiple nodes

I have recently updated one of the articles on the subject in our support knowledge base and wanted to test-drive this content with you: https://www.devexpress.com/kb=T271022


Since the Application Model basically represents a skeleton of the application UI, based on which visual controls for supported platforms are created at runtime, updates to various options in the source UI metadata (both at design time and runtime) can be a good and often platform-agnostic alternative to customizing underlying controls directly in Controllers or other UI entities (examples: one, two, three). The most difficult thing is to perform this update at the right moment or using the right event in the View life cycle!
Even though this may sound like a quite an advanced topic, this is one of the core concepts for our framework, which I recommend you get familiar with.







Your feedback is welcome, as always!

We also hope to use this KB as a base for future updates of the online documentation at  Concepts > Application Model  for easier discoverability, so your early feedback on the main methods I described is welcome. In particular, I would greatly appreciate your comments on whether you experienced the scenarios needed runtime Application Model updates and exactly which techniques you used (e.g., #2.1, 2.2 or all ).


Thursday, February 23, 2017

How to refresh View appearance after making changes to the Application Model in code

With XAF v16.2.4, you can apply Application Model changes to a View without recreating it. To do this, save the Frame's View to a variable and then unlink it from the Frame by passing null to the SetView method. After that, make the required changes to the model, call the LoadModel method with the false parameter and then set the saved View back to the Frame using the SetView method. Here is the generic code illustrating this pattern:

View view = Frame.View;
if(Frame.SetView(null, true, null, false)) {
    // Make required changes with the model here. 
    // ... 
    view.LoadModel(false);
    Frame.SetView(view);
}

You can find a full ViewController code for accomplishing the two most popular WinForms scenarios benefiting from this capability in the https://www.devexpress.com/kb=S173664 article (switching a ListView editor type and MasterDetailMode). 
This video also illustrates how it works in the application UI in action. 


Leave a comment if this is something you are going to try right now!
As always, please report any issues using the https://www.devexpress.com/ask service. Thanks in advance!


Tuesday, November 8, 2016

How to show a specific View at application startup, right after the logon window or after loading the main window

I have recently updated my old KB article with several solutions and wanted to bring this for your information:


Here is the information on typical scenarios to get a better understanding of where this article can be applied: 

"One may want to show a dialog view at startup (after logging in). Typically, this view appears after the successful logon and allows a user to select or edit personal or global settings such as current password, company, currency, language, etc. Also, it may be often required to display this View as modal before a user can access the navigation menu or any other forms in the application. In other scenarios, it may be required to display a kind of notifications popup right after loading the main window, with unread messages, active orders, etc."





As always, it would be great to hear whether you are already using these techniques (specify approach #) in your XAF apps or you had to invent new solutions for a similar task. I am looking forward to hearing from you in the comments.


Thursday, September 15, 2016

How to provide a specific View layout for users of certain security roles

I would like to quickly promote a recent update to our old Code Example in the support database: https://www.devexpress.com/example=E274
I hope you find this solution helpful. Let me know in case of any questions, suggestions or share your experience with other XAFers on how you are doing a similar task at the moment. Thanks!

Scenario:
This example demonstrates how to show a custom View against a role of the currently logged user. Custom Views were created and customized through the Model Editor for each role separately. For more convenience, custom Views have a name of a role in the Id attribute. For instance: Contact_ListView_Administrators, Contact_DetailView_Administrators, Contact_ListView_Users, Contact_DetailView_Users, etc. You may consider a specific naming convention, for example, to add a role name to the end of the view name. Use User and Admin user names with empty password to login into the application.



Implementation details:
There is E274.Module\Controllers\CustomizeViewAgainstRoleMainWindowController that tracks View showing using theXafApplication.ViewCreating event and replaces the default View's Id with a custom Id found in the Application Model by the role name. 

Monday, December 21, 2015

JFYI - New RefreshXXX methods allowing to reload the underlying data source of a View or ViewItem

Just wanted to make sure you are aware of this small usability improvement, which will help you accomplish daily development tasks easier and in more intuitively.

From https://www.devexpress.com/Support/Center/Question/Details/S170756 (done in v15.2.4):

The following methods are added to the View and ViewItem classes:[C#]
public virtual void RefreshDataSource()
public void Refresh(bool refreshDataSource)
Internally, the Refresh method calls RefreshDataSource when the refreshDataSource parameter is set to true.

The RefreshDataSource method overloads are:
ListView.RefreshDataSource -  calls the CollectionSourceBase.Reload method;
DetailView.RefreshDataSource  - calls the IObjectSpace.ReloadObject method and passes the DetailView.CurrentObject object to it;
ListPropertyEditor.RefreshDataSource - calls the ListView.RefreshDataSource method;
DetailPropertyEditor.RefreshDataSource - calls the DetailView.RefreshDataSource method.

Monday, December 14, 2015

DashboardView - Allowing end-users to delete created dashboards via the application UI

In v15.2.4 we have added the DeleteDashboardsController which provides the DeleteDashboard Action. This Action is located in the Tools category and invokes a popup dialog with a list of all dashboard views defined in the user's model differences.

In this popup you can select one or more dashboards and click Delete to remove them. The DeleteDashboardsController.CanDeleteParentGroup property specifies whether or not the dashboard's parent group is deleted when you remove the last dashboard in this group. 

The DeleteDashboard Action is active when there are dashboards that can be deleted and the EnableCreation property of the Options | Dashboards node is set to true in the Application Model.


Previously, it was only possible to manage these user-defined dashboards via the Model Editor or in code. So, I hope you will now be able to enable this feature for your clients without the fear of being overloaded with support calls about removing unwanted stuff.

You can find more information on this XAF feature in the online docs here:

Friday, October 2, 2015

Avoiding repetitive customizations for Views of the same type or subclasses via the Model Editor - YOUR FEEDBACK IS NEEDED

Prerequisites

Imagine you have the following data model classes:

class Party {...}

class Person : Party {...}
class Organization: Party {...}



XAF automatically generated several default root and nested Views for them in the Application Model. You can also create custom Views via the Model Editor on your own. For instance, you might end up with the following list under the Views node:


    Party_ListView
    Person_ListView1
    Person_ListViewN
    Organization_ListView1
    Organization_ListViewN



Scenario


Imagine your first goal is to customize the appearance of the ListView for the base class - Party_ListView according to your client needs.To accomplish this, you locate the Party_ListView node in the Model Editor and make various customizations to its columns. In particular, 1. edit captions for the Photo, Address1, Address2 columns; moved the Photo column after the Address1 and Address2 ones; 2. made changes to the ListView node properties such as set IsGroupPanelVisible, AllowEdit and other options in the property grid.


What if your second goal is to have a similar appearance for other ListViews where Party records are shown, e.g., Person_ListView, Organization_ListView1, Party_LookupListView or even Company_Persons_ListView (see the poll questions in the end)?


Wednesday, September 9, 2015

How to reset View customizations made by end-users (UPDATE)

I invite you to test an updated version of the previous E1897 solution (it is now marked as obsolete), which we are planning to include in v15.2 by default. The new solution supports both WinForms and ASP.NET apps and also works for both the root and nested Views (e.g., the ones embedded into ListPropertyEditor and DetailPropertyEditor):


Thursday, June 26, 2014

ViewController or Action activation for multiple Views or target object types via the TargetViewId property

I would like to highlight a small usability improvement that may help you write less and simpler code when configuring a target View for which a ViewController or an Action will be available.

Let's consider a couple scenarios where it may be helpful:
1. Your ViewController/Action should work for Views corresponding to absolutely unrelated Object1 and Object2 types (there is no inheritance between them and they are not descended from a common base class).
2. Your ViewController/Action should work for several specific Views of a certain object type, but be unavailable for other Views of the same type (e.g., be active for Object3_ListView, Object3_DetailView, but not for Object3_LookupListView and others).

Starting with version 14.1, you can implement the second scenario by setting the TargetViewId property of your ViewController or Action by providing a semicolon-separated list of Views, for which your element should be activated. Previously, you should have written the View.Id checks manually before executing your code. Please consider the following example:

Wednesday, January 29, 2014

How to traverse and customize XAF View items and their underlying controls

!!!The contents of this article were moved to www.devexpress.com/issue=KA18895!!!

XAF UI screen structure
To better understand how to access and customize XAF building blocks, let's briefly describe how default UI screens are generated in XAF.

On the top of the UI screen structure, there are Windows and Frames linked to Templates (Frame.Template), which are usually platform-dependent entities (e.g., forms, web pages or user controls) defining the Frame's content structure and appearance in the UI. 
There are several types of Frames (both platform-agnostic and platform-dependent), depending on whether their represented UI element has a parent or not: e.g. Frames of the main application form or of a separate dialog form are called Windows, because they are independent and have no parents, while a nested ListView's Frame is not Window.

Here is the respective classes hierarchy for clarity:

   Frame
      • NestedFrame
      • Window
             • WinWindow
             • WebWindow
                    • PopupWindow


Frame is a container for Controllers (Frame.Controllers or Frame.GetController<T>) that help implement a custom behavior and interaction within a Frame. Note that all application logic and behavior is basically provided by Controllers (both system and user-defined). For easier access, Controllers provide useful properties, events and virtual methods to access the Frame itself and its contents at various points in its life cycle (Controller.Frame, WindowController.Window, ViewController.View, ViewController.ObjectSpace, Controller.Activated, etc.).

Both Frame and Window also serve as a site for a View (Frame.View, ViewController.View). Any View placed within a Frame consists of special sub-elements or items, which represent the actual content of a UI screen. Technically, each of these View elements wraps a certain visual control to display or edit specific data in the UI . View items can be even be complex enough to host other Views.

The placement of content items on the screen, as well as many of their basic settings, are determined by the information from the Application Model corresponding to that View node (e.g., the Views | Address_DetailView node you can see in the Model Editor tool). To learn more on how Views present or lay out their content, check out the following important concepts:
At once, the Application Model is used to preserve the state or current settings of the View and its controls until the next time.

This article is mainly devoted to Views, so please check out the UI Element Overview article if you are interested to learn more on the structure of XAF screens.

View and Item types
The following diagram displays hereditary relations of various View types:

   View
       • CompositeView
              • DashboardView
              • ObjectView
                     • DetailView
                     • ListView


There are also several built-in ViewItem types:

   ViewItem
       • ControlDetailItem

       • DashboardViewItem

       • PropertyEditor
             • ListPropertyEditor
             • DetailPropertyEditor
             • WinPropertyEditor
                    • DXPropertyEditor
                          • StringPropertyEditor
                          • ...
             • WebPropertyEditor
                    • ASPxPropertyEditor
                          • ASPxStringPropertyEditor
                          • ...

       • ActionContainerViewItem
              • WinActionContainerViewItem
              • WebActionContainerViewItem

       • StaticText
                • StaticTextDetailItem (DevExpress.ExpressApp.W**.Editors)

       • StaticImage
                • StaticImageDetailItem (DevExpress.ExpressApp.W**.Editors)
       • ...

Remember that for each of these built-in View and Item types there are corresponding elements in the Application Model (IModelDetailView, IModelDashboardView, IModelListView, IModelViewItem, IModelPropertyEditor, etc. that determine their content, layout structure and other options.

The use of certain View items varies and depends on the View type:

    • PropertyEditor and its descendants for various data types, including user-defined and built-in platform-agnostic (ListPropertyEditor,  DetailPropertyEditor) and platform-dependent editors;
    • other ViewItem descendants, including user-defined and built-in ActionContainerViewItem, ControlDetailItem, StaticText, StaticImage, etc.

    • Other ViewItem descendants, including ActionContainerViewItem , ControlDetailItem, StaticText, StaticImage, etc. (user-defined and built-in)

ListView is a special type of View, which consists of  two internal items - ListEditorViewItem and NestedFrameItem. These two service items are undocumented and are not supposed to be used by customers in their code. Instead, ListView provides the additional mechanism for accessing the ListView's content and controls - List Editors.



Traversing View items and their controls
The View, ViewItem and ListEditor abstractions provided by our framework are very often used to access underlying form controls for various customizations. In accomplishing this task, it is common to implement a custom ViewController descendant targeted to a required View type and handle its events or override virtual methods, depending on the moment when you need to perform this customization.

• To access a ViewItem or ListEditor object from a ViewController, it is common to override the OnActicated virtual method (or handle the Activated event) of a custom ViewController class descendant, because View items and List Editors are available right after View creation. Of course, you can use other events and methods which occur later according to the View life cycle.

• To access the underlying control of a ViewItem, it is common to handle the ViewItem.ControlCreated event, while accessing the ListEditor's control usually requires handling the View.ControlsCreated or ListEditor.ControlsCreated events (or overriding the OnViewControlsCreated method) within a custom ViewController class descendant. Of course, you can use other events and methods which occur later according to the View life cycle.

When using this approach, a starting point is almost always the ViewController.View property that gives you access to the underlying elements or API to access them. It is often required to cast the View object to a concrete View type, e.g., DetailView or ListView, to gain access to more View type specific options.


For your reference, here is the list of most popular APIs used to implement common tasks with View items:

    • To identify a ViewItem, use the ViewItem.Id property.

    • To identify a PropertyEditor, use the PropertyEditor.Id or PropertyEditor.PropertyName properties.

    • To access ALL ViewItem objects, you can use the CompositeView.Items property (see Example #1 below).

    • To access ViewItem objects of a specific type, you can use the CompositeView.GetItems<T> method (see Example #2 below).

    • To access a ViewItem object by its Id, you can use the CompositeView.FindItem method (see Example #3 below).

    •  To access a ListEditor object of a certain ListView, use the ListView.Editor property. It is often required to cast it to a specific ListEditor type to access the underlying control and additional options. Refer to the Access Grid Control Properties help article for an example.

    •  To access the underlying control of View items or editors, use the ViewItem.Control or ListEditor.Control properties. Most built-in View items and editors also provide specialized properties for easier access, e.g., GridListEditor.Grid, ASPxPropertyEditor.Editor, ASPxLookupPropertyEditor.DropDown, etc.


Practical implementation considerations
0. Due to WinForms or ASP.NET platform specifics, underlying controls of View items and List Editors may not be immediately ready for customization right after the control is created. It is often required to subscribe to specialized control events indicating their "ready" state:
    WinForms: handle the HandleCreated, VisibleChanged or ParentChanged events of the     System.Windows.Forms.Control object (in certain cases it is even required to apply customizations via the Control.BeginInvoke method).
    ASP.NET: handle the Init, Load or PreRender server side events of the System.Web.UI.Control object or handle the PagePreRender event of the static WebWindow.CurrentRequestWindow object. Of     course, it is also fine to perform certain customizations on the client side via JavaSript.

1. When iterating through the CompositeView.Items collection (via foreach, for or LINQ) to locate a required ViewItem object, it is often helpful to test its type or the ViewItem.Id property, corresponding to the Id property of a respective item node in the Application Model (see Example #1 below).

2. To avoid casting the ViewController.View object to a required View type every time, inherit your custom controller class not from the base ViewController class, but from the generic ViewController<ViewType> or ObjectViewController<ViewType, ObjectType> types, whose View property type will be the same as the specified ViewType parameter (see Example #4 below).

3. Take into account the CompositeView.DelayedItemsInitialization option when writing code that accesses the ViewItem.Control property. Since the default value for this option is true, then in most scenarios it is recommended to handle the ViewItem.ControlCreated event of the required ViewItem object or test whether the properties accessed are null (see Example #2 below). Refer to the Access Editor Settings article for more example code on this task.

4. There are some specifics when accessing items that host or contain other Views inside DetailView or DashboardView. Such Views are typically embedded into a container View with the help of special type of platform-agnostic ViewItem classes:
    • ListPropertyEditor is used to represent collection properties of business objects in DetailView (see Example #4 below);
    • DetailPropertyEditor is used to represent aggregated reference properties of business objects in DetailView (see Example #5 below);
    • DashboardViewItem is used to represent nested Views of any type within a DashboardView (see Example #7 below).

5. Embedded or nested Views are hosted within a NestedFrame, which is technically a descendant of the Frame type with the ViewItem property that can help you identify what is hosted inside it (see Example #8 below).

6. To access a parent View from the ViewItem object, use the ViewItem.View property (see Example #9 below).

7. The View.Control property is very rarely used or should not be used at all. Instead, it is better to use specialized properties of a certain View object, e.g., ListView.Editor.Control, CompositeView.LayoutManager.Container.

8. Certain List Editors (e.g., GridListEditor) may internally instantiate PropertyEditor objects (e.g., for grid column editors) to create underlying controls for viewing or editing business object properties in a ListView. However, these PropertyEditor objects are not "alive" and are primarily only used as a template to create a control. Thus you should not try to access these service PropertyEditor objects in your code via a ViewController.

9. If you need to apply the same global customization to the underlying PropertyEditor control in both ListView and DetailView, then you may consider implementing a descendant of the corresponding PropertyEditor type (and overriding its virtual methods) instead of implementing a ViewController and writing different code for both ListView and DetailView.

10. Normally you should not modify the Application Model information corresponding to a certain View or its items in your code when underlying controls are already created, unless you preserve the current control state into your own model options. When doing so, bear in mind that your model changes will not be taken into account until the next control creation. So, a general rule here is that you either need to customize the control directly or customize the corresponding Application Model options before the control is created and rendered.

11. When ListView and DetailView are shown together (MasterDetailMode = ListViewAndDetailView), you can use the ListView.EditView property to access the embedded detail form and its content.

Check out the following code examples to better understand these points: 

using System;
using System.Linq;
using DevExpress.ExpressApp;
using System.Collections.Generic;
using DevExpress.ExpressApp.Layout;
using DevExpress.ExpressApp.Editors;

namespace MainDemo.Module.Controllers {
    public class MyViewController : ViewController {
        public MyViewController() {
            TargetViewType = ViewType.DetailView;
        }
        protected override void OnActivated() {
            base.OnActivated();
            //Example #1
            foreach(ViewItem item in ((DetailView)View).Items) {
                if((item is ControlDetailItem) & item.Id == "Item1") { /*...*/ }
            }
            //Example #2
            foreach(ActionContainerViewItem item in ((DetailView)View).GetItems<ActionContainerViewItem>()) {
                if(item.Control != null) { /*...*/                }
                else {
                    item.ControlCreated += (s, e) => { /*...*/ };
                }
            }
            //Example #3
            PropertyEditor editor = ((DetailView)View).FindItem("Property") as PropertyEditor;
            //Example #4
            ListPropertyEditor editorForCollectionProperty = ((DetailView)View).FindItem("CollectionProperty") as ListPropertyEditor;
            editorForCollectionProperty.ControlCreated += (s, e) => {
                ListView nestedListView = ((ListPropertyEditor)s).ListView;
                NestedFrame nestedFrame = ((ListPropertyEditor)s).Frame as NestedFrame;
            };
            //Example #5
            DetailPropertyEditor editorForAggregatedReferenceProperty = ((DetailView)View).FindItem("AggregatedReferenceProperty") as DetailPropertyEditor;
            editorForAggregatedReferenceProperty.ControlCreated += (s, e) => {
                DetailView nestedDetailView = ((DetailPropertyEditor)s).DetailView;
                NestedFrame nestedFrame = ((DetailPropertyEditor)s).Frame as NestedFrame;
            };
        }
    }
    //Example #6
    public class MyGenericDashboardViewViewController : ViewController<DashboardView> {
        protected override void OnActivated() {
            base.OnActivated();
            foreach(DashboardViewItem item in View.GetItems<DashboardViewItem>()) {
                //Example #7
                item.ControlCreated += (s, e) => {
                    DashboardViewItem dashboardViewItem = (DashboardViewItem)s;
                    View nestedView = dashboardViewItem.InnerView;
                    NestedFrame nestedFrame = dashboardViewItem.Frame as NestedFrame;
                    //Example #8                    
                    DashboardView containerView1 = (DashboardView)nestedFrame.View;
                    //Or                    
                    DashboardView containerView2 = (DashboardView)dashboardViewItem.View;
                    //Example #9                    
                    ViewItem nestedFrameViewItem = nestedFrame.ViewItem;
                };
            }
        }
    }
}


See Also