I have a LookupEdit on a WinForms application; the EditValue is bound to a model where the property is an int?
and marked with Required
attribute applied. The main issue I'm having is that the DX control detects the attribute, which would be fine but then prevents the control from losing focus until a value is selected from the list. You can't even close the application once the error provider shows.
If you run the app and try clicking into the text box, the LookupEdit validates and prevents the focus from leaving the control. Ideally I'd like to just let the focus change and show the error provider. How can I 1) configure the LookupEdit to let it lose focus even if the control is invalid & also configure where the error icon shows or 2) tell DX to ignore data annotations? Our form code will enable/disable a save button if the model is not valid, I don't need DX to force the user to remain on the control until its valid.
Create a Windows Forms project named DxDataAnnotations
with .Net 4.7.2 and add the devexpress.win
NuGet package using version 19.1.6. Here's the form code (with models included):
Form1.cs
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Forms;
namespace DxDataAnnotations {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
protected override void OnShown(EventArgs e) {
base.OnShown(e);
managersBindingSource.DataSource = new BindingList<Manager>(new[] {
new Manager(1, "Manager 1"),
new Manager(2, "Manager 2"),
new Manager(3, "Manager 3"),
new Manager(4, "Manager 4"),
new Manager(5, "Manager 5"),
new Manager(6, "Manager 6")
});
employeeBindingSource.DataSource = new Employee();
}
}
public sealed class Employee {
[Required]
public int? ManagerId { get; set; }
}
public sealed class Manager {
public Manager(int id, string name) {
ManagerId = id;
ManagerName = name;
}
public int ManagerId { get; }
public string ManagerName { get; }
}
}
Form1.Designer.cs
namespace DxDataAnnotations {
partial class Form1 {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.lookUpEdit1 = new DevExpress.XtraEditors.LookUpEdit();
this.employeeBindingSource = new System.Windows.Forms.BindingSource(this.components);
this.managersBindingSource = new System.Windows.Forms.BindingSource(this.components);
this.textBox1 = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.lookUpEdit1.Properties)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.employeeBindingSource)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.managersBindingSource)).BeginInit();
this.SuspendLayout();
//
// lookUpEdit1
//
this.lookUpEdit1.DataBindings.Add(new System.Windows.Forms.Binding("EditValue", this.employeeBindingSource, "ManagerId", true));
this.lookUpEdit1.Location = new System.Drawing.Point(207, 93);
this.lookUpEdit1.Name = "lookUpEdit1";
this.lookUpEdit1.Properties.Buttons.AddRange(new DevExpress.XtraEditors.Controls.EditorButton[] {
new DevExpress.XtraEditors.Controls.EditorButton(DevExpress.XtraEditors.Controls.ButtonPredefines.Combo)});
this.lookUpEdit1.Properties.Columns.AddRange(new DevExpress.XtraEditors.Controls.LookUpColumnInfo[] {
new DevExpress.XtraEditors.Controls.LookUpColumnInfo("ManagerId", "Manager Id", 78, DevExpress.Utils.FormatType.Numeric, "", false, DevExpress.Utils.HorzAlignment.Far, DevExpress.Data.ColumnSortOrder.None, DevExpress.Utils.DefaultBoolean.Default),
new DevExpress.XtraEditors.Controls.LookUpColumnInfo("ManagerName", "Manager Name", 82, DevExpress.Utils.FormatType.None, "", true, DevExpress.Utils.HorzAlignment.Near, DevExpress.Data.ColumnSortOrder.None, DevExpress.Utils.DefaultBoolean.Default)});
this.lookUpEdit1.Properties.DataSource = this.managersBindingSource;
this.lookUpEdit1.Properties.DisplayMember = "ManagerName";
this.lookUpEdit1.Properties.ValueMember = "ManagerId";
this.lookUpEdit1.Size = new System.Drawing.Size(398, 20);
this.lookUpEdit1.TabIndex = 0;
//
// employeeBindingSource
//
this.employeeBindingSource.AllowNew = false;
this.employeeBindingSource.DataSource = typeof(DxDataAnnotations.Employee);
//
// managersBindingSource
//
this.managersBindingSource.DataSource = typeof(DxDataAnnotations.Manager);
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(222, 135);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 1;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.lookUpEdit1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.lookUpEdit1.Properties)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.employeeBindingSource)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.managersBindingSource)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private DevExpress.XtraEditors.LookUpEdit lookUpEdit1;
private System.Windows.Forms.BindingSource employeeBindingSource;
private System.Windows.Forms.BindingSource managersBindingSource;
private System.Windows.Forms.TextBox textBox1;
}
}
What about removing the validation attribute from the model (directly or via wrapping the model instances into the specific DTO)?
Anyway, here are some answers:
Ideally I'd like to just let the focus change and show the error provider.
Take a look at the Form.AutoValidate property which manages how a control validates its data when it loses user input focus. The AutoValidate.EnableAllowFocusChange
value allows the user to move focus between editors despite of validation result.
...tell DX to ignore data annotations?
You can avoid validation by using the DevExpress.Data.Utils.AnnotationAttributes.AllowValidation
static option:
DevExpress.Data.Utils.AnnotationAttributes.AllowValidation = DevExpress.Utils.DefaultBoolean.False;