### Configuration and Setup
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/00-START-HERE.txt
Information on configuration properties, XAML examples, and default settings for the DataFormView control. This section guides users on how to set up and customize the form's overall behavior and appearance.
```APIDOC
## Configuration
### Description
Covers the configuration properties, XAML examples, and default values for the DataFormView control.
### Namespace
DevExpress.Maui.DataForm
### Related Files
- `configuration.md`
### Properties
Refer to `configuration.md` for a detailed list of configurable properties and their usage.
```
--------------------------------
### Usage Examples
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/00-START-HERE.txt
Provides practical code examples demonstrating various ways to use the DataFormView control, from basic setup to complex scenarios.
```APIDOC
## Usage Examples
### Description
Contains practical code examples illustrating the usage of the DataFormView control in different scenarios.
### Related Files
- `usage-examples.md`
### Examples
Refer to `usage-examples.md` for runnable code patterns and real-world application examples.
```
--------------------------------
### Minimal Data Form Setup
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/usage-examples.md
Demonstrates the minimal setup for a DataFormView by binding it to a simple data object. The form automatically generates editors and labels based on the object's properties.
```csharp
public class PersonalInfo
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
dataForm.DataObject = new PersonalInfo();
}
}
```
```xaml
```
--------------------------------
### Basic DataFormView Setup
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/dataformview.md
Demonstrates the basic initialization of DataFormView with a DataObject and setting editor box and validation modes.
```csharp
var dataForm = new DataFormView
{
DataObject = new PersonalInfo(),
EditorBoxMode = EditorBoxMode.Filled,
ValidationMode = ValidationMode.PropertyChanged
};
```
--------------------------------
### Complete DataForm Layout and Styling Example
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/layout-and-styling.md
Demonstrates a comprehensive setup for a MAUI DataForm, including data model attributes for layout and styling, and XAML for the DataFormView configuration. This example showcases group headers, row separators, and various editor-specific display options.
```csharp
// Data model with layout attributes
public class EmployeeInfo
{
[DataFormItemPosition(RowOrder = 1, ItemOrderInRow = 1)]
[DataFormTextEditor(InplaceLabelText = "First Name")]
[DataFormDisplayOptions(
GroupName = "Personal Information",
LabelIcon = "person")]
public string FirstName { get; set; }
[DataFormItemPosition(RowOrder = 1, ItemOrderInRow = 2)]
[DataFormTextEditor(InplaceLabelText = "Last Name")]
[DataFormDisplayOptions(
GroupName = "Personal Information",
IsLabelVisible = false)]
public string LastName { get; set; }
[DataFormItemPosition(RowOrder = 2, ItemOrderInRow = 1)]
[DataFormTextEditor(Placeholder = "Email")]
[DataFormDisplayOptions(
GroupName = "Contact Information",
LabelIcon = "email")]
[EmailAddress]
public string Email { get; set; }
[DataFormItemPosition(RowOrder = 2, ItemOrderInRow = 2)]
[DataFormMaskedEditor(
Mask = "+1 (000) 000-0000",
Placeholder = "Phone")]
[DataFormDisplayOptions(
GroupName = "Contact Information",
LabelIcon = "phone")]
public string Phone { get; set; }
[DataFormDisplayOptions(GroupName = "Employment",
LabelMinWidth = 150)]
[DataFormDateEditor]
public DateTime HireDate { get; set; }
[DataFormDisplayOptions(GroupName = "Employment")]
[DataFormComboBoxEditor(IsFilterEnabled = true)]
public DepartmentType Department { get; set; }
}
// XAML setup
```
--------------------------------
### Complete Edit Form Example with DataForm
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/usage-examples.md
A comprehensive example of an editable form including data binding, image display, and custom validation for email. This snippet demonstrates setting up the DataForm, handling save actions, and performing validation before saving.
```csharp
public class Customer : BindableBase
{
private string firstName;
[Required]
public string FirstName
{
get => firstName;
set { firstName = value; RaisePropertyChanged(); }
}
private string email;
[EmailAddress]
[Required]
public string Email
{
get => email;
set { email = value; RaisePropertyChanged(); }
}
private string photoPath;
public string PhotoPath
{
get => photoPath;
set { photoPath = value; RaisePropertyChanged(); }
}
}
public partial class EditPage : ContentPage
{
public EditPage()
{
InitializeComponent();
var customer = new Customer();
dataForm.DataObject = customer;
dataForm.PropertyValidation += ValidateProperties;
}
private void ValidateProperties(object sender,
DataFormPropertyValidationEventArgs e)
{
if (e.PropertyName == "Email" && e.NewValue != null)
{
MailAddress res;
if (!MailAddress.TryCreate(e.NewValue.ToString(), out res))
{
e.HasError = true;
e.ErrorText = "Invalid email";
}
}
}
private void OnSaveClicked(object sender, EventArgs e)
{
dataForm.Commit();
if (dataForm.GetPropertyValidationError("Email") == null)
{
// Save to database
SaveCustomer();
}
}
private async void SaveCustomer()
{
await DisplayAlert("Success", "Customer saved", "OK");
}
}
```
```xaml
```
--------------------------------
### Basic DataForm Setup
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/README.md
Demonstrates the simplest way to create a DataForm by binding it to a data object. This automatically generates editors for all public properties.
```xaml
```
--------------------------------
### MVVM Customer Edit Form Example
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/binding-and-mvvm.md
This example shows a complete MVVM implementation for a customer edit form, including ViewModel, View, and XAML. The ViewModel handles data and commands, while the View uses DataFormView for data entry and validation.
```csharp
// ViewModel
public class CustomerEditViewModel : BindableBase
{
private Customer editedCustomer;
public Customer EditedCustomer
{
get => editedCustomer;
set
{
editedCustomer = value;
RaisePropertyChanged();
}
}
private ICommand saveCommand;
public ICommand SaveCommand =>
saveCommand ?? (saveCommand = new Command(ExecuteSave, CanSave));
public CustomerEditViewModel()
{
EditedCustomer = new Customer
{
FirstName = "John",
LastName = "Doe",
Email = "john@example.com"
};
}
private void ExecuteSave()
{
// Save to database
SaveCustomer(EditedCustomer);
}
private bool CanSave()
{
return EditedCustomer != null;
}
private void SaveCustomer(Customer customer)
{
// Database save implementation
}
}
// View
public partial class CustomerEditPage : ContentPage
{
public CustomerEditPage()
{
InitializeComponent();
BindingContext = new CustomerEditViewModel();
}
private void OnValidateProperty(object sender,
DevExpress.Maui.DataForm.DataFormPropertyValidationEventArgs e)
{
if (e.PropertyName == "Email" && !IsValidEmail(e.NewValue?.ToString()))
{
e.HasError = true;
e.ErrorText = "Invalid email format";
}
}
private bool IsValidEmail(string email)
{
try
{
var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email;
}
catch
{
return false;
}
}
}
// XAML
```
--------------------------------
### Complete DataForm Validation Example
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/validation.md
Demonstrates how to use data annotations for validation and implement custom validation logic in the PropertyValidation event handler. This example covers required fields, string length, email format, phone format, age range, and password strength.
```csharp
public class Customer
{
[Required(ErrorMessage = "First name is required")]
[StringLength(50)]
public string FirstName { get; set; }
[Required(ErrorMessage = "Last name is required")]
[StringLength(50)]
public string LastName { get; set; }
[EmailAddress(ErrorMessage = "Invalid email format")]
[Required(ErrorMessage = "Email is required")]
public string Email { get; set; }
[Phone(ErrorMessage = "Invalid phone format")]
public string Phone { get; set; }
[Range(18, 120, ErrorMessage = "Age must be 18-120")]
public int Age { get; set; }
[StringLength(100, MinimumLength = 8,
ErrorMessage = "Password must be 8-100 characters")]
public string Password { get; set; }
}
// In Page code-behind
public partial class CustomerEditPage : ContentPage
{
public CustomerEditPage()
{
InitializeComponent();
var customer = new Customer();
dataForm.DataObject = customer;
dataForm.ValidationMode = ValidationMode.PropertyChanged;
// Add custom validation
dataForm.PropertyValidation += ValidateCustomer;
}
private void ValidateCustomer(object sender,
DataFormPropertyValidationEventArgs e)
{
// Validate password strength
if (e.PropertyName == "Password")
{
var password = e.NewValue?.ToString() ?? "";
bool hasUpper = password.Any(char.IsUpper);
bool hasLower = password.Any(char.IsLower);
bool hasDigit = password.Any(char.IsDigit);
if (!hasUpper || !hasLower || !hasDigit)
{
e.HasError = true;
e.ErrorText = "Password must contain uppercase, lowercase, and numbers";
}
}
}
private async void OnSaveClicked(object sender, EventArgs e)
{
dataForm.Commit();
// Check for validation errors
var firstNameError = dataForm.GetPropertyValidationError("FirstName");
var emailError = dataForm.GetPropertyValidationError("Email");
if (firstNameError != null || emailError != null)
{
await DisplayAlert("Validation Error",
"Please correct the validation errors", "OK");
return;
}
// Proceed with save
await SaveCustomer();
}
}
```
--------------------------------
### IPickerSourceProvider from Database
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
An implementation that fetches data from a database using DbContext. It handles 'Department', 'Manager', and 'Status' properties by querying the database. Requires DbContext and DI setup.
```csharp
public class DatabaseProvider : IPickerSourceProvider
{
private readonly DbContext dbContext;
public DatabaseProvider(DbContext dbContext)
{
this.dbContext = dbContext;
}
public IEnumerable GetSource(string propertyName)
{
return propertyName switch
{
"Department" => dbContext.Departments.ToList(),
"Manager" => dbContext.Employees.Where(e => e.IsManager).ToList(),
"Status" => GetStatusEnumValues(),
_ => null
};
}
private IEnumerable GetStatusEnumValues()
{
return Enum.GetValues(typeof(EmployeeStatus))
.Cast()
.Select(e => e.ToString());
}
}
// Usage in MauiProgram
builder.Services.AddSingleton();
builder.Services.AddSingleton();
```
--------------------------------
### Quick Reference
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/00-START-HERE.txt
A quick lookup guide for properties and methods of the DataFormView control, useful for experienced developers needing fast access to API details.
```APIDOC
## Quick Reference
### Description
A quick lookup resource for properties and methods of the DataFormView control.
### Related Files
- `quick-reference.md`
### Lookup
Refer to `quick-reference.md` for a concise list of properties and methods.
```
--------------------------------
### Initialize DataForm with Data Provider
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/usage-examples.md
Initializes the MAUI ContentPage and sets the DataObject and PickerSourceProvider for the data form. This setup enables the ComboBox editors to function correctly.
```csharp
public partial class EmployeePage : ContentPage
{
public EmployeePage()
{
InitializeComponent();
dataForm.DataObject = new Employee();
dataForm.PickerSourceProvider = new ComboBoxDataProvider();
}
}
```
--------------------------------
### Load Raw Asset at Runtime
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/CS/AddingDataEditorsAtRuntime/Resources/Raw/AboutAssets.txt
This C# code demonstrates how to load a raw asset file (e.g., AboutAssets.txt) that has been deployed with your application package. It uses FileSystem.OpenAppPackageFileAsync to get a stream to the file and then reads its contents.
```csharp
async Task LoadMauiAsset()
{
using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt");
using var reader = new StreamReader(stream);
var contents = reader.ReadToEnd();
}
```
--------------------------------
### DataForm Keyboard Type Examples
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/types.md
Demonstrates how to apply specific keyboard types to DataForm editors using attributes. This allows for tailored input interfaces for different data fields.
```csharp
[DataFormTextEditor(Keyboard = "Email")]
public string Email { get; set; }
[DataFormMaskedEditor(Mask = "+0 (000) 000-0000", Keyboard = "Telephone")]
public string Phone { get; set; }
```
--------------------------------
### Implement Conditional Data Provider
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
Implement IPickerSourceProvider to fetch data conditionally based on other property values. This example shows how to provide states based on a selected country and cities based on a selected state.
```csharp
public class ConditionalDataProvider : IPickerSourceProvider
{
public IEnumerable GetSource(string propertyName)
{
// Access other property values from the data object
var dataForm = GetCurrentDataForm(); // Implementation depends on context
var dataObject = dataForm?.DataObject as Employee;
if (propertyName == "State")
{
// Return states for the selected country
if (dataObject?.Country == "USA")
return GetUSStates();
else if (dataObject?.Country == "Canada")
return GetCanadianProvinces();
else
return null;
}
if (propertyName == "City")
{
// Return cities for the selected state
if (dataObject?.State == "CA")
return GetCaliforniaCities();
else
return GetOtherCities(dataObject?.State);
}
return null;
}
private IEnumerable GetUSStates()
{
return new[] { "CA", "NY", "TX", "FL", "IL" };
}
private IEnumerable GetCanadianProvinces()
{
return new[] { "BC", "AB", "ON", "QC", "MB" };
}
private IEnumerable GetCaliforniaCities()
{
return new[] { "Los Angeles", "San Francisco", "San Diego" };
}
private IEnumerable GetOtherCities(string state)
{
return new[] { "City 1", "City 2" };
}
}
```
--------------------------------
### Example: Email Validation
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/validation.md
Implement email format validation by checking if the new value contains an '@' symbol. Set HasError and ErrorText when validation fails.
```csharp
dataForm.PropertyValidation += (sender, e) =>
{
if (e.PropertyName == "Email")
{
var email = e.NewValue?.ToString();
if (string.IsNullOrEmpty(email) || !email.Contains("@"))
{
e.HasError = true;
e.ErrorText = "Please enter a valid email address";
}
}
};
```
--------------------------------
### Data Binding and MVVM Integration
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/00-START-HERE.txt
Guides on integrating the DataFormView with data binding and MVVM patterns. This section is key for developers following modern .NET MAUI development practices.
```APIDOC
## Binding and MVVM
### Description
Explains how to effectively use the DataFormView with data binding and Model-View-ViewModel (MVVM) patterns in .NET MAUI applications.
### Namespace
DevExpress.Maui.DataForm
### Related Files
- `binding-and-mvvm.md`
### Patterns
Refer to `binding-and-mvvm.md` for detailed examples and explanations of MVVM integration.
```
--------------------------------
### Example: Cross-Property Validation
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/validation.md
Perform validation that compares the 'ConfirmPassword' field with the 'Password' field. Access the DataObject to retrieve other field values.
```csharp
dataForm.PropertyValidation += (sender, e) =>
{
if (e.PropertyName == "ConfirmPassword")
{
// Access data object to compare with Password field
var dataObject = dataForm.DataObject as Customer;
if (dataObject?.Password != e.NewValue?.ToString())
{
e.HasError = true;
e.ErrorText = "Passwords do not match";
}
}
};
```
--------------------------------
### Styled Form with Groups and Icons
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/usage-examples.md
Shows how to customize the appearance of the DataForm using attributes to group fields, set placeholders, and assign icons to labels. This example defines a data model with various editor types and display options.
```csharp
public class EmployeeInfo
{
[DataFormItemPosition(RowOrder = 1, ItemOrderInRow = 1)]
[DataFormTextEditor(Placeholder = "First Name")]
[DataFormDisplayOptions(
GroupName = "Name",
LabelIcon = "person_outline")]
public string FirstName { get; set; }
[DataFormItemPosition(RowOrder = 1, ItemOrderInRow = 2)]
[DataFormTextEditor(Placeholder = "Last Name")]
[DataFormDisplayOptions(GroupName = "Name")]
public string LastName { get; set; }
[DataFormTextEditor(Placeholder = "Email")]
[DataFormDisplayOptions(
GroupName = "Email & Phone",
LabelIcon = "email")]
public string Email { get; set; }
[DataFormMaskedEditor(
Mask = "+1 (000) 000-0000",
Placeholder = "Phone")]
[DataFormDisplayOptions(
GroupName = "Email & Phone",
LabelIcon = "phone")]
public string Phone { get; set; }
[DataFormTextEditor(Placeholder = "Address")]
[DataFormDisplayOptions(GroupName = "Address")]
public string Address { get; set; }
[DataFormTextEditor(Placeholder = "City")]
[DataFormDisplayOptions(GroupName = "Address")]
public string City { get; set; }
[DataFormTextEditor(Placeholder = "State")]
[DataFormDisplayOptions(GroupName = "Address")]
public string State { get; set; }
[DataFormMaskedEditor(
Mask = "00000",
Placeholder = "Zip")]
[DataFormDisplayOptions(GroupName = "Address")]
public string Zip { get; set; }
[DataFormComboBoxEditor(IsFilterEnabled = true)]
[DataFormDisplayOptions(
GroupName = "Employment",
LabelMinWidth = 150)]
public DepartmentType Department { get; set; }
[DataFormDateEditor]
[DataFormDisplayOptions(GroupName = "Employment")]
public DateTime HiredAt { get; set; }
}
public enum DepartmentType { Sales, Engineering, Support, HR }
```
```xaml
```
```csharp
public partial class AppearancePage : ContentPage
{
public AppearancePage()
{
InitializeComponent();
dataForm.DataObject = new EmployeeInfo
{
FirstName = "Jane",
Email = "jane@example.com"
};
}
}
```
--------------------------------
### Complete Model with DataForm Attributes
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/dataform-items.md
An example of a complete model class using various DataForm attributes to configure editors, display options, and validation. This demonstrates a comprehensive approach to form definition.
```csharp
public class PersonalInfo
{
[DataFormItemPosition(RowOrder = 1, ItemOrderInRow = 1)]
[DataFormTextEditor(InplaceLabelText = "First Name")]
[DataFormDisplayOptions(LabelIcon = "person_outline", GroupName = "Profile")]
public string FirstName { get; set; }
[DataFormItemPosition(RowOrder = 1, ItemOrderInRow = 2)]
[DataFormTextEditor(InplaceLabelText = "Last Name")]
[DataFormDisplayOptions(IsLabelVisible = false, GroupName = "Profile")]
public string LastName { get; set; }
[DataFormPasswordEditor]
[DataFormDisplayOptions(GroupName = "Profile")]
[StringLength(64, MinimumLength = 8, ErrorMessage = "Min 8 characters")]
[Required(ErrorMessage = "Required")]
public string Password { get; set; }
[DataFormMaskedEditor(Mask = "+0 (000) 000-0000", Keyboard = "Telephone")]
[DataFormDisplayOptions(GroupName = "Contact")]
public string Phone { get; set; }
[DataFormComboBoxEditor]
[DataFormDisplayOptions(GroupName = "Profile")]
public Gender Gender { get; set; }
[DataFormDateEditor]
[DataFormDisplayOptions(GroupName = "Profile")]
public DateTime? BirthDate { get; set; }
}
public enum Gender { Female, Male, RatherNotSay }
```
--------------------------------
### Customer Data Object Definition
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/README.md
Defines a simple Customer class with properties that will be used by the DataForm. This example shows basic property types like string and nullable DateTime.
```csharp
public class Customer
{
public string FirstName { get; set; }
public string Email { get; set; }
public DateTime? BirthDate { get; set; }
}
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
dataForm.DataObject = new Customer();
}
}
```
--------------------------------
### Two-Way Binding Example
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/binding-and-mvvm.md
Demonstrates how MAUI DataForm automatically handles two-way data binding. Changes in the form update the object, and changes in the object update the form editors.
```csharp
public partial class EditPage : ContentPage
{
private Customer customer;
public EditPage()
{
InitializeComponent();
customer = new Customer();
dataForm.DataObject = customer;
}
// Update object programmatically
private void OnExternalDataChange()
{
customer.FirstName = "Jane"; // Form updates automatically
customer.Email = "jane@example.com";
}
}
```
--------------------------------
### Dynamically Show/Hide Fields in DataForm
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/advanced-patterns.md
Control the visibility of form fields based on the values of other fields. This example demonstrates how to show the 'CompanyName' field only when the 'OrderType' is set to 'Business'.
```csharp
public class OrderForm
{
[DataFormDisplayOptions(GroupName = "Order")]
public OrderType OrderType { get; set; }
[DataFormDisplayOptions(GroupName = "Billing")]
public string BillingAddress { get; set; }
// Company field only visible for B2B orders
[DataFormDisplayOptions(GroupName = "Billing")]
public string CompanyName { get; set; }
}
public partial class OrderPage : ContentPage
{
private OrderForm order = new();
public OrderPage()
{
InitializeComponent();
dataForm.DataObject = order;
dataForm.PropertyValidation += OnPropertyValidation;
}
private void OnPropertyValidation(object sender,
DataFormPropertyValidationEventArgs e)
{
// Show/hide company field based on order type
var companyItem = dataForm.Items
.FirstOrDefault(i => i.FieldName == "CompanyName");
if (companyItem != null)
{
companyItem.IsVisible = (order.OrderType == OrderType.Business);
}
// Require company for B2B orders
if (e.PropertyName == "CompanyName" &&
order.OrderType == OrderType.Business)
{
if (string.IsNullOrEmpty(e.NewValue?.ToString()))
{
e.HasError = true;
e.ErrorText = "Company name required for B2B orders";
}
}
}
}
public enum OrderType { Personal, Business }
```
--------------------------------
### Configure ComboBox Editor with DataFormComboBoxEditor
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
Use the DataFormComboBoxEditor attribute to configure ComboBox editors. This example shows how to specify ValueMember and DisplayMember for the DepartmentCode and Status properties.
```csharp
public class Employee
{
[DataFormComboBoxEditor(
ValueMember = "Code",
DisplayMember = "Name")]
public int DepartmentCode { get; set; }
[DataFormComboBoxEditor(
DisplayMember = "Name")]
public string Status { get; set; }
}
```
--------------------------------
### Configure DataFormComboBoxEditor
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/types.md
Configures a ComboBox editor within a DataForm to use specific value and display members for its items. This example shows how to bind a 'Department' property to a list of departments.
```csharp
[DataFormComboBoxEditor(
ValueMember = "Code",
DisplayMember = "Name")]
public int Department { get; set; }
```
--------------------------------
### Async Data Validation in MAUI DataForm
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/advanced-patterns.md
Implement asynchronous validation for a property in the MAUI DataForm. This example shows how to queue validation tasks on a background thread to avoid blocking the UI and handle the validation result on the main thread.
```csharp
public class AsyncValidationPage : ContentPage
{
private HttpClient httpClient;
private Email emailData = new();
public AsyncValidationPage(HttpClient client)
{
httpClient = client;
InitializeComponent();
dataForm.DataObject = emailData;
dataForm.PropertyValidation += OnPropertyValidation;
}
private void OnPropertyValidation(object sender,
DataFormPropertyValidationEventArgs e)
{
if (e.PropertyName == "Email")
{
// Don't block UI with async validation
// Queue validation on background
Task.Run(() => ValidateEmailAsync(e));
}
}
private async Task ValidateEmailAsync(
DataFormPropertyValidationEventArgs e)
{
var email = e.NewValue?.ToString();
try
{
var response = await httpClient
.GetAsync($"/api/validate-email?email={email}");
var result = await response.Content.ReadAsAsync();
MainThread.BeginInvokeOnMainThread(() =>
{
if (!result.IsValid)
{
e.HasError = true;
e.ErrorText = result.ErrorMessage;
}
});
}
catch (Exception ex)
{
MainThread.BeginInvokeOnMainThread(() =>
{
e.HasError = true;
e.ErrorText = "Could not validate email";
});
}
}
public class ValidationResult
{
public bool IsValid { get; set; }
public string ErrorMessage { get; set; }
}
}
```
--------------------------------
### Implement IPickerSourceProvider for Departments
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/types.md
Provides a sample implementation of IPickerSourceProvider to supply a list of Department objects for a 'Department' property. This is useful for populating dropdowns in DataForm editors.
```csharp
public class DepartmentPickerProvider : IPickerSourceProvider
{
public IEnumerable GetSource(string propertyName)
{
if (propertyName == "Department")
{
return new List
{
new Department { Code = 1, Name = "Sales" },
new Department { Code = 2, Name = "Engineering" }
};
}
return null;
}
}
// Usage
dataForm.PickerSourceProvider = new DepartmentPickerProvider();
```
--------------------------------
### Get Property Validation Error
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/dataformview.md
Retrieves the validation error message for a specified property. Returns null if the property is valid.
```csharp
public string GetPropertyValidationError(string propertyName)
string error = dataForm.GetPropertyValidationError("Email");
if (error != null)
MessageBox.Show(error);
```
--------------------------------
### Retrieve All DataForm Items
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/quick-reference.md
Get a list of all items currently present in the data form. This is useful for iterating or performing bulk operations.
```csharp
var items = dataForm.Items.ToList();
```
--------------------------------
### Basic IPickerSourceProvider Implementation
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
A simple implementation of IPickerSourceProvider that returns a hardcoded list of statuses for the 'Status' property. Use this for straightforward, static data sources.
```csharp
public class StatusProvider : IPickerSourceProvider
{
public IEnumerable GetSource(string propertyName)
{
if (propertyName == "Status")
{
return new List
{
"Active",
"Inactive",
"Pending",
"Suspended"
};
}
return null;
}
}
// Usage
dataForm.PickerSourceProvider = new StatusProvider();
```
--------------------------------
### DataForm Events
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/quick-reference.md
Subscribe to these events to handle specific DataForm actions and state changes. For example, use `PropertyValidation` to intercept validation events.
```csharp
dataForm.PropertyValidation += (s, e) => { };
dataForm.ItemsSourceChanged += (s, e) => { };
dataForm.DataObjectChanged += (s, e) => { };
```
--------------------------------
### Include Raw Assets in .csproj
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/CS/AddingDataEditorsAtRuntime/Resources/Raw/AboutAssets.txt
This XML snippet shows how to configure your .csproj file to include raw assets from the Resources\Raw directory and its subdirectories. The LogicalName ensures the asset is deployed with its original path and name.
```xml
```
--------------------------------
### Example: Conditional Required Field
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/validation.md
Validate if the 'CompanyName' is required only when 'IsCompanyCustomer' is true. This demonstrates conditional validation based on other data object properties.
```csharp
dataForm.PropertyValidation += (sender, e) =>
{
if (e.PropertyName == "CompanyName")
{
var dataObject = dataForm.DataObject as Customer;
if (dataObject?.IsCompanyCustomer == true && string.IsNullOrEmpty(e.NewValue?.ToString()))
{
e.HasError = true;
e.ErrorText = "Company name is required for business customers";
}
}
};
```
--------------------------------
### Range Validation
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/validation.md
Validates that a numeric property falls within a specified range. Custom error messages guide users on acceptable values.
```csharp
[Range(0, 150, ErrorMessage = "Age must be between 0 and 150")]
public int Age { get; set; }
```
--------------------------------
### Apply Mask to DataFormView Editor
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/CS/EditFormExample/Readme.md
Use the Mask property on DataFormMaskedItem to define input masks for editors. This example sets a phone number mask.
```xml
```
--------------------------------
### Register IPickerSourceProvider with Dependency Injection
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
Register your custom IPickerSourceProvider implementation (e.g., ApiDataProvider) as a singleton in the MauiProgram.cs file. This makes it available for injection throughout your application.
```csharp
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder()
.UseMauiApp()
.ConfigureFonts(fonts => { /* ... */ });
builder.Services
.AddSingleton()
.AddSingleton();
return builder.Build();
}
}
```
--------------------------------
### Implementing Picker Data Source Provider
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/quick-reference.md
Provide custom data sources for picker items by implementing the IPickerSourceProvider interface. This allows dynamic population of dropdown lists based on property names.
```csharp
public class MyProvider : IPickerSourceProvider
{
public IEnumerable GetSource(string propertyName)
{
if (propertyName == "Department")
return departments;
return null;
}
}
dataForm.PickerSourceProvider = new MyProvider();
```
--------------------------------
### Embed Custom MAUI View in DataForm
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/dataform-items.md
Use DataFormCustomItem to embed any MAUI view as an editor, binding it to a field. This example shows embedding an image view.
```csharp
public class DataFormCustomItem : DataFormItem
```
```xaml
```
--------------------------------
### CustomerViewModel Implementation
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/usage-examples.md
This ViewModel handles the data for the Customer object and includes a SaveCommand. It initializes the EditedItem with default values.
```csharp
public class CustomerViewModel : BindableBase
{
private Customer editedItem;
public Customer EditedItem
{
get => editedItem;
set
{
editedItem = value;
RaisePropertyChanged();
}
}
private ICommand saveCommand;
public ICommand SaveCommand =>
saveCommand ?? (saveCommand = new Command(ExecuteSave));
public CustomerViewModel()
{
EditedItem = new Customer
{
FirstName = "John",
LastName = "Doe",
Email = "john@example.com",
Phone = "(555) 123-4567",
Company = "Acme Corp"
};
}
private async void ExecuteSave()
{
await Shell.Current.DisplayAlert("Success",
$"Saved {EditedItem.FirstName} {EditedItem.LastName}",
"OK");
}
}
```
--------------------------------
### Group DataFormView Editors Using LabelIcon
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/CS/EditFormExample/Readme.md
Use the LabelIcon property on DataFormTextItem to visually group editors. This example assigns the 'editorsname' icon to the FirstName field.
```xml
```
--------------------------------
### Get Specific Property Validation Error
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/validation.md
Retrieves the validation error message for a specific property. Call this method to check the validation status of an individual field.
```csharp
// Get error for specific property
string error = dataForm.GetPropertyValidationError("Email");
```
--------------------------------
### Implement Caching for Data Loading
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
Implement caching within a custom IPickerSourceProvider to avoid repeated data loads. Data is loaded once and stored in a dictionary.
```csharp
public class CachedProvider : IPickerSourceProvider
{
private Dictionary cache = new();
public IEnumerable GetSource(string propertyName)
{
if (!cache.ContainsKey(propertyName))
{
cache[propertyName] = LoadData(propertyName);
}
return cache[propertyName];
}
private IEnumerable LoadData(string propertyName) { ... }
```
--------------------------------
### IPickerSourceProvider with API and Caching
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
An implementation that fetches data from a remote API and caches the results. It supports 'Department' and 'Status' properties and uses HttpClient for API calls. Caching improves performance by reducing redundant API requests.
```csharp
public class ApiDataProvider : IPickerSourceProvider
{
private readonly HttpClient httpClient;
private Dictionary cache = new();
public ApiDataProvider(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public IEnumerable GetSource(string propertyName)
{
if (cache.ContainsKey(propertyName))
return cache[propertyName];
var data = FetchDataAsync(propertyName).GetAwaiter().GetResult();
cache[propertyName] = data;
return data;
}
private async Task FetchDataAsync(string propertyName)
{
string endpoint = propertyName switch
{
"Department" => "/api/departments",
"Status" => "/api/statuses",
_ => null
};
if (endpoint == null) return null;
try
{
var response = await httpClient.GetAsync(endpoint);
var json = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize>(json);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Error fetching {propertyName}: {ex.Message}");
return null;
}
}
}
```
--------------------------------
### Handle PropertyValidation Event for Email
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/types.md
Provides an example of handling the DataFormView.PropertyValidation event to implement custom validation logic for an 'Email' property. It checks for the presence of '@' in the email address.
```csharp
dataForm.PropertyValidation += (sender, e) =>
{
if (e.PropertyName == "Email")
{
var email = e.NewValue?.ToString();
if (!email?.Contains("@") ?? true)
{
e.HasError = true;
e.ErrorText = "Invalid email format";
}
}
};
```
--------------------------------
### IPickerSourceProvider for Multiple Properties
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/picker-source-provider.md
An implementation that handles data sources for multiple properties ('Department', 'Position', 'Status') using a switch statement. This is useful when a single provider manages data for various fields.
```csharp
public class EmployeeDataProvider : IPickerSourceProvider
{
public IEnumerable GetSource(string propertyName)
{
switch (propertyName)
{
case "Department":
return GetDepartments();
case "Position":
return GetPositions();
case "Status":
return GetStatuses();
default:
return null;
}
}
private IEnumerable GetDepartments()
{
return new List
{
new Department { Code = 1, Name = "Sales" },
new Department { Code = 2, Name = "Engineering" },
new Department { Code = 3, Name = "Marketing" },
new Department { Code = 4, Name = "Support" }
};
}
private IEnumerable GetPositions()
{
return new List
{
"Manager",
"Senior Developer",
"Developer",
"Analyst",
"Intern"
};
}
private IEnumerable GetStatuses()
{
return new List { "Active", "Inactive" };
}
}
```
--------------------------------
### Validate Email Input in DataFormView
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/CS/EditFormExample/Readme.md
Implement a validation event handler for the Email property to ensure valid email formats. This example checks if the input can be parsed as a MailAddress.
```csharp
private void ValidateCustomerProperties(object sender, DevExpress.Maui.DataForm.DataFormPropertyValidationEventArgs e) {
if (e.PropertyName == "Email" && e.NewValue != null) {
MailAddress res;
if (!MailAddress.TryCreate((string)e.NewValue, out res)) {
e.HasError = true;
e.ErrorText = "Invalid email";
}
}
}
```
--------------------------------
### Apply Theming with AppThemeBinding
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/configuration.md
Configure platform-specific themes for DataForm elements using 'AppThemeBinding' in XAML.
```xaml
```
--------------------------------
### DataFormView Basic Usage
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/quick-reference.md
Demonstrates the basic usage of the DataFormView control in XAML and code-behind for setting the DataObject and committing changes.
```csharp
```
```csharp
dataForm.DataObject = new Customer();
dataForm.Commit();
```
--------------------------------
### DataFormView Configuration Properties
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/quick-reference.md
Shows how to configure behavior, appearance, and layout properties of the DataFormView, such as auto-generation, commit mode, validation mode, colors, padding, and group collapsing.
```csharp
// Behavior
dataForm.IsAutoGenerationEnabled = true; // Auto-generate items
dataForm.CommitMode = CommitMode.LostFocus; // When to save
dataForm.ValidationMode = ValidationMode.LostFocus;
// Appearance
dataForm.EditorBoxMode = EditorBoxMode.Filled;
dataForm.EditorLabelColor = Colors.DarkGray;
dataForm.EditorLabelWidth = 100;
dataForm.IsEditorLabelVisible = true;
// Layout
dataForm.ContentPadding = new Thickness(12, 16);
dataForm.GroupHeaderBackgroundColor = Colors.LightGray;
dataForm.AllowCollapseGroups = true;
dataForm.RowSeparatorColor = Colors.Gray;
dataForm.RowSeparatorThickness = 1;
```
--------------------------------
### Configure Multiline Text Editor
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/dataform-items.md
Use DataFormMultilineEditor for string properties that require multi-line text input. Specify placeholder text.
```csharp
[DataFormMultilineEditor(Placeholder = "Comments")]
public string Notes { get; set; }
```
--------------------------------
### Customize DataFormView Editor Label Appearance
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/CS/EditFormExample/Readme.md
Set EditorLabelColor and EditorLabelWidth to customize the appearance of labels within the DataFormView. This example sets the color to a static resource and the width to 40.
```xaml
```
--------------------------------
### Picker Source Provider Configuration for DataFormView in C#
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/configuration.md
Implement and assign a custom IPickerSourceProvider to DataFormView in C# to dynamically supply data for picker editors.
```csharp
public class DepartmentProvider : IPickerSourceProvider
{
public IEnumerable GetSource(string propertyName)
{
if (propertyName == "Department")
return GetDepartmentList();
if (propertyName == "Status")
return GetStatusList();
return null;
}
private IEnumerable GetDepartmentList()
{
return new List
{
new Department { Code = 1, Name = "Sales" },
new Department { Code = 2, Name = "Engineering" }
};
}
private IEnumerable GetStatusList()
{
return new List { "Active", "Inactive" };
}
}
// Usage
dataForm.PickerSourceProvider = new DepartmentProvider();
```
--------------------------------
### Integrate MAUI DataForm with MVVM Community Toolkit
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/binding-and-mvvm.md
Utilize MVVM Community Toolkit's ObservableObject and RelayCommand for efficient MVVM implementation. Bind DataObject to an ObservableProperty and use RelayCommand for actions.
```csharp
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
public partial class CustomerViewModel : ObservableObject
{
[ObservableProperty]
private Customer editedItem = new();
[RelayCommand]
private async Task Save()
{
await Database.SaveAsync(EditedItem);
await Shell.Current.GoToAsync("..");
}
}
// XAML
```
--------------------------------
### Data Form with Various Editor Types
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/usage-examples.md
Illustrates how to configure different editor types for Data Form fields using attributes. This includes text, email, phone (masked), date, password, combo box, and multiline editors, along with grouping and display options.
```csharp
public class CompleteForm
{
[DataFormDisplayOptions(GroupName = "Personal")]
public string FirstName { get; set; }
[DataFormTextEditor(Placeholder = "Email")]
[DataFormDisplayOptions(GroupName = "Contact")]
[EmailAddress]
public string Email { get; set; }
[DataFormMaskedEditor(Mask = "+1 (000) 000-0000")]
[DataFormDisplayOptions(GroupName = "Contact")]
public string Phone { get; set; }
[DataFormDateEditor]
[DataFormDisplayOptions(GroupName = "Personal")]
public DateTime BirthDate { get; set; }
[DataFormPasswordEditor]
[StringLength(64, MinimumLength = 8)]
[DataFormDisplayOptions(GroupName = "Security")]
public string Password { get; set; }
[DataFormComboBoxEditor]
[DataFormDisplayOptions(GroupName = "Personal")]
public Gender Gender { get; set; }
[DataFormMultilineEditor(Placeholder = "Comments")]
[DataFormDisplayOptions(GroupName = "Notes")]
public string Comments { get; set; }
}
public enum Gender { Female, Male, NotSpecified }
```
--------------------------------
### Cross-Field Validation for Date Ranges
Source: https://github.com/devexpress-examples/maui-data-form/blob/24.2.3+/_autodocs/advanced-patterns.md
Implement custom validation logic to ensure that the end date is always after the start date. This validator attaches to the DataForm's PropertyValidation event.
```csharp
public class DateRangeValidator
{
private DataFormView dataForm;
public DateRangeValidator(DataFormView form)
{
dataForm = form;
}
public void Validate(object sender,
DataFormPropertyValidationEventArgs e)
{
if (e.PropertyName == "EndDate")
{
var dataObject = dataForm.DataObject as DateRange;
if (dataObject?.StartDate > (DateTime)e.NewValue)
{
e.HasError = true;
e.ErrorText = "End date must be after start date";
}
}
if (e.PropertyName == "StartDate")
{
var dataObject = dataForm.DataObject as DateRange;
if ((DateTime)e.NewValue > dataObject?.EndDate)
{
e.HasError = true;
e.ErrorText = "Start date must be before end date";
}
}
}
}
public class DateRange
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
// Usage
var validator = new DateRangeValidator(dataForm);
dataForm.PropertyValidation += validator.Validate;
```