EditValuesContainer Class

Contains information on a data row currently being edited by an end-user via an edit form.

Namespace: DevExpress.Mobile.DataGrid

Assembly: DevExpress.Mobile.Grid.v18.1.dll

Declaration

public class EditValuesContainer :
    Object,
    INotifyPropertyChanged
Public Class EditValuesContainer
    Inherits Object
    Implements INotifyPropertyChanged

An EditValuesContainer object contains information about a data row currently being edited and serves as a data context (binding source) for a template that defines presentation of a row edit form and is assigned to the GridControl.EditFormContent property.

Examples

GridControl allows you to substitute the default row edit form with a custom form. This example explains how to do this.

In this application, the grid is bound to a collection of orders. Each data row in the grid represents an individual order and displays the following information:

  • Ordered product name (the Product column)
  • Product unit price (the Price column)
  • Number of ordered product units (the Quantity column)
  • Order total value (the Total column)
  • A value indicating whether an order is shipped (the Shipped column)

The default row edit form in this grid looks like the following.

iOS Android
GridControl_iOS_DefaulRowEditForm GridControl_Android_DefaulRowEditForm

This example demonstrates how to create a custom form to add new data rows and another form to edit existing rows.

  • Add New Order Form

    This form is invoked on tapping New Item Row in the grid and allows an end user to add a new data row (create a new order). On this form, an end user can select a product name via a Picker control, and set the number of ordered product units via a Slider control. A unit price is automatically shown for the selected product, and the order total value is automatically calculated.

    iOS Android
    GridControl_iOS_CustomNewRowForm GridControl_Android_CustomNewRowForm
  • Edit Order Form

    This form is invoked on double-tapping a cell or selecting Edit Cell from the popup menu. It allows an end user to modify existing data rows. On this form, product name and unit price are shown in Lable controls and cannot be changed. An end user can change the number of ordered product units via a Slider control and use the Switch control to set whether the order is shipped.

    iOS Android
    GridControl_iOS_CustomRowEditForm GridControl_Android_CustomRowEditForm

To create a custom row edit form and show it instead of the default form, execute the steps below.

  1. Specify a custom form view. In this example, it is a ContentView descendant with a set of labels and editors inside (see the CustomFormEditorContent.cs file). This view's BindingContext is an EditValuesContainer object. Labels and editors are bound to data fields via the EditValuesContainer.GetBindingPath method with data field names passed as parameters.

    The EditValuesContainer.IsNewRow property identifies whether a from is invoked for a new or existing row.

    Custom form captions are implemented by using the mechanism of localization.

  2. Create a DataTemplate instance for your custom form view and assign this template to the GridControl.EditFormContent property (see the MainPage.xaml.cs file).
  3. Set the GridControl.RowEditMode property to RowEditMode.Popup to show a form instead of an in-place row editor.
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using DevExpress.Mobile.DataGrid;
using DevExpress.Mobile.DataGrid.Theme;
using System.Globalization;
using DevExpress.Mobile.DataGrid.Localization;

namespace CustomEditFormDemo {

    class EditFormLocalizer : GridLocalizer {
        public void SetEditItemFormCaption() {
            AddString(GridStringId.EditingForm_LabelCaption, "Edit Order");
        }
        public void SetNewItemFormCaption() {
            AddString(GridStringId.EditingForm_LabelCaption, "Add New Order");
        }
    }


    public class CustomEditFormContent : ContentView {
        public TestOrdersRepository ViewModel { get; set; }

        public CustomEditFormContent() {
            HorizontalOptions = LayoutOptions.FillAndExpand;
            VerticalOptions = LayoutOptions.FillAndExpand; 
            GridLocalizer.Active = new EditFormLocalizer();
        }

        protected override void OnBindingContextChanged () {
            base.OnBindingContextChanged ();
            EditFormLocalizer localizer = GridLocalizer.Active as EditFormLocalizer;

            if ((BindingContext as EditValuesContainer).IsNewRow) {
                if (localizer != null) {
                    localizer.SetNewItemFormCaption();
                }
                Content = CreateNewItemFormContent();
            }
            else {
                if (localizer != null) {
                    localizer.SetEditItemFormCaption();
                }
                Content = CreateEditItemFormContent ();
            }
        }

        View CreateNewItemFormContent() {
            Grid layoutGrid = CreateGrid(4);
            FillFormGrid(layoutGrid, true);
            return layoutGrid;
        }

        View CreateEditItemFormContent() {
            Grid layoutGrid = CreateGrid(5);
            FillFormGrid(layoutGrid, false);
            return layoutGrid;
        }

        Grid CreateGrid(int rowsCount) {
            Grid layoutGrid = new Grid();

            layoutGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Auto });
            layoutGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(200, GridUnitType.Star) });

            for (int i = 0; i < rowsCount; i++) {
                layoutGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
            }

            layoutGrid.RowSpacing = 20;
            layoutGrid.ColumnSpacing = 20;

            return layoutGrid;
        }

        void FillFormGrid(Grid layoutGrid, bool isNewItemForm) {
            FillLabels(layoutGrid, isNewItemForm);
            FillEditors(layoutGrid, isNewItemForm);
        }

        void FillLabels(Grid layoutGrid, bool isNewItemForm) {
            Label productName = new Label() { Text = "Product name:", 
                                              FontSize = 18, VerticalOptions = LayoutOptions.Center };
            Label productUnitPrice = new Label() { Text = "Price per product unit:", 
                                                   FontSize = 18, VerticalOptions = LayoutOptions.Center };
            Label quantity = new Label() { Text = "The number of ordered units:", 
                                           FontSize = 18, VerticalOptions = LayoutOptions.Start };
            Label total = new Label() { Text = "Total cost:", 
                                        FontSize = 18, VerticalOptions = LayoutOptions.Center };
            Label isShipped = null;

            if (!isNewItemForm) {
                isShipped = new Label() { Text = "Has this order been shipped?", 
                                          FontSize = 18, VerticalOptions = LayoutOptions.Center };
            }

            layoutGrid.Children.Add(productName, 0, 0);
            layoutGrid.Children.Add(productUnitPrice, 0, 1);
            layoutGrid.Children.Add(quantity, 0, 2);
            layoutGrid.Children.Add(total, 0, 3);

            if (!isNewItemForm) {
                layoutGrid.Children.Add(isShipped, 0, 4);
            }
        }

        void FillEditors(Grid layoutGrid, bool isNewItemForm) {
            View productName;

            // Display a product name in a label in the Edit Item form 
            // or change a product name by using a picker in the New Item form.
            if (isNewItemForm) {
                productName = new Picker() { HorizontalOptions = LayoutOptions.FillAndExpand, 
                                             VerticalOptions = LayoutOptions.Center};
                InitProductPickerValues(productName as Picker);
            }
            else {
                productName = new Label() { HorizontalOptions = LayoutOptions.FillAndExpand, 
                                            VerticalOptions = LayoutOptions.Center, 
                                            FontAttributes = FontAttributes.Bold, FontSize = 18 };
                productName.SetBinding(Label.TextProperty, 
                                        new Binding(EditValuesContainer.GetBindingPath("Product.Name")));
            }

            // Display a product unit price in a form.
            Int32ToPriceStringConverter priceConverter = new Int32ToPriceStringConverter();
            Label priceLabel = new Label () { HorizontalOptions = LayoutOptions.FillAndExpand, 
                                              VerticalOptions = LayoutOptions.Center, FontSize = 18 };
            priceLabel.SetBinding (Label.TextProperty, EditValuesContainer.GetBindingPath ("Product.UnitPrice"), 
                                    BindingMode.Default, priceConverter);

            // Modify the number of ordered units via a slider.
            StackLayout quantityStack = new StackLayout () { Orientation = StackOrientation.Vertical, 
                                                             VerticalOptions = LayoutOptions.CenterAndExpand };
            Label quantityLabel = new Label () { XAlign = TextAlignment.Start, 
                                                 VerticalOptions = LayoutOptions.Center, FontSize = 18};
            Slider quantitySlider = new Slider () { Maximum = 99, Minimum = 10 };
            quantitySlider.SetBinding (Slider.ValueProperty, EditValuesContainer.GetBindingPath ("Quantity"), 
                                       BindingMode.TwoWay, new Int32ToDoubleConverter());
            quantityLabel.BindingContext = quantitySlider;
            quantityLabel.SetBinding(Label.TextProperty, "Value", BindingMode.OneWay, new DoubleToInt32Converter());
            quantityStack.Children.Add(quantityLabel);
            quantityStack.Children.Add(quantitySlider);

            // Display the order total value calculated automatically.
            Label totalLabel = new Label () { XAlign = TextAlignment.Start, 
                                              VerticalOptions = LayoutOptions.Center, FontSize = 18 };
            totalLabel.PropertyChanged += OnTotalPropertyChanged;
            totalLabel.SetBinding(Label.TextProperty, EditValuesContainer.GetBindingPath("Total"), 
                                  BindingMode.OneWay, priceConverter);

            if (!isNewItemForm) {
                priceLabel.FontAttributes = FontAttributes.Bold;
                quantityLabel.FontAttributes = FontAttributes.Bold;
                totalLabel.FontAttributes = FontAttributes.Bold;
            }

            // Add created elements to a form.
            layoutGrid.Children.Add(productName, 1, 0);
            layoutGrid.Children.Add(priceLabel, 1, 1);
            layoutGrid.Children.Add(quantityStack, 1, 2);
            layoutGrid.Children.Add(totalLabel, 1, 3);

            // Show a switch in the Edit Item form allowing end-users to set whether or not an order is shipped.
            Switch isShipped = new Switch() { VerticalOptions = LayoutOptions.Center, 
                                              HorizontalOptions = LayoutOptions.Start };
            isShipped.SetBinding(Switch.IsToggledProperty, EditValuesContainer.GetBindingPath("Shipped"));
            if (!isNewItemForm) {
                layoutGrid.Children.Add(isShipped, 1, 4);
            }
        }

        void InitProductPickerValues(Picker picker) {
            EditValuesContainer valuesContainer = BindingContext as EditValuesContainer;
            String productName = valuesContainer.Values["Product.Name"].ToString();
            int selectedItemIndex = -1;

            foreach (Product product in ViewModel.Products) {
                if (productName == product.Name) {
                    selectedItemIndex = picker.Items.Count;
                }

                picker.Items.Add(product.Name);
            }

            picker.SelectedIndexChanged += OnProductNameSelectedIndexChanged;

            if (selectedItemIndex >= 0) {
                picker.SelectedIndex = selectedItemIndex;
            }
        }

        void OnProductNameSelectedIndexChanged(object sender, EventArgs e) {
            EditValuesContainer valuesContainer = BindingContext as EditValuesContainer;
            Picker picker = sender as Picker;

            if (picker.SelectedIndex < 0) {
                return;
            }

            String productName = picker.Items[picker.SelectedIndex];

            valuesContainer.Values["Product.Name"] = productName;

            Product product = ViewModel.Products.Find(p => p.Name == productName);

            valuesContainer.Values["Product.UnitPrice"] = product.UnitPrice;
        }

        void OnTotalPropertyChanged (object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Label label = (sender as Label);
            if (e.PropertyName == Label.TextProperty.PropertyName && !String.IsNullOrWhiteSpace (label.Text)) {
                Int32 value = (Int32)((label.BindingContext as EditValuesContainer).Values ["Total"]);
                if (value > 2000) {
                    label.TextColor = Color.Green; } 
                else {
                    if (value < 500) {
                        label.TextColor = Color.Red; } 
                    else {
                        label.TextColor = ThemeManager.Theme.CellCustomizer.Font.Color;}
                }
            }
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             x:Class="CustomEditFormDemo.MainPage"
             xmlns:dxGrid="clr-namespace:DevExpress.Mobile.DataGrid;assembly=DevExpress.Mobile.Grid.v15.1">
      <ContentPage.Padding>
        <OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
    </ContentPage.Padding>
    <dxGrid:GridControl x:Name="grid" ItemsSource="{Binding Orders}" 
                         NewItemRowVisibility="true" InitNewRow="OnInitNewItemRow">
            <dxGrid:GridControl.Columns>
             <dxGrid:TextColumn FieldName="Product.Name" Caption="Product" Width="170"/>
             <dxGrid:NumberColumn FieldName="Product.UnitPrice" Caption="Price" DisplayFormat="C0"/>
             <dxGrid:NumberColumn FieldName="Quantity"/>
             <dxGrid:NumberColumn FieldName="Total" 
                                  UnboundType="Integer" UnboundExpression="[Quantity] * [Product.UnitPrice]" 
                                  DisplayFormat="C0" IsReadOnly="True"/>
             <dxGrid:SwitchColumn FieldName="Shipped"/>
         </dxGrid:GridControl.Columns>
    </dxGrid:GridControl>
</ContentPage>
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using DevExpress.Mobile.DataGrid;

namespace CustomEditFormDemo
{    
    public partial class MainPage : ContentPage
    {
        TestOrdersRepository model;
        public MainPage ()
        {
            InitializeComponent ();

            model = new TestOrdersRepository ();
            BindingContext = model;


            DataTemplate editFormContentTemplate = new DataTemplate(GetTemplate);
            grid.EditFormContent = editFormContentTemplate;
            grid.RowEditMode = RowEditMode.Popup;
        }

        object GetTemplate() {
            return new CustomEditFormContent() { ViewModel = model };
        }

        void OnInitNewItemRow(object sender, InitNewRowEventArgs e) {
            e.EditableRowData.SetFieldValue("Quantity", model.MinimumQuantity);
            e.EditableRowData.SetFieldValue("Product.Name", model.Products[0].Name);
        }
    }
}

Inheritance

Object
EditValuesContainer

See Also