I have written my own Validator and although the validator appears to be working (as it does display the Text property when invalid) the ValidationSummary does not display the ErrorMessage property, or anything, when validation fails. Interestingly, it appears that it fails to even display the Text property when I add another control with a validator to the page. What am I doing wrong?
public class RequiredCheckBoxListValidator : BaseValidator
{
private CheckBoxList _list;
private int _requiredCount = 1;
public int RequiredCount
{
get { return _requiredCount; }
set { _requiredCount = value; }
}
public RequiredCheckBoxListValidator()
{
EnableClientScript = false;
}
protected override bool ControlPropertiesValid()
{
Control control = FindControl(ControlToValidate);
if (control != null)
{
_list = (CheckBoxList)control;
return (_list != null);
}
else
{
return false;
}
}
protected override bool EvaluateIsValid()
{
return (_list.Items.Cast<ListItem>().Where(li => li.Selected).Count() == _requiredCount);
}
}
It would help to see your clientside info.
Without that, my guesses are to check ShowSummary on the validtorsummary to make sure it is not hiding the summary, and to see if the validators and summary are in separate UpdatePanels.
Related
I set a button by default to IsEnabled = false. After the two Entries have an input and are validated, the button should change to IsEnabled = true.
This is what I have so far on my MainPage:
var button = new Button
{
Text = "Text",
.
.
.
IsEnabled = false
};
var entry1 = new Entry
{
.
.
.
};
var entry1 = new Entry
{
.
.
.
};
button.SetBinding(Button.CommandProperty, "EnableButtonComand");
On my ViewModel I have this:
bool isValidatedEntry1 = false;
bool isValidatedEntry2 = false;
bool isAllValidated = false;
public Command EnableButtonCommand { get; }
public bool IsValidatedEntry1
{
get { return isValidatedEntry1; }
set { isValidatedEntry1 = value; OnPropertyChanged("IsValidatedEntry1"); OnPropertyChanged("IsAllValidated"); }
}
public bool IsValidatedEntry2
{
get { return isValidatedEntry2; }
set { isValidatedEntry2= value; OnPropertyChanged("IsValidatedEntry2"); OnPropertyChanged("IsAllValidated"); }
}
public bool IsAllValidated
{
get { return isAllValidated; }
set { if (IsValidatedEntry1 && IsValidatedEntry2)
{
isAllValidated = true;
}
else
{
isAllValidated = false;
}
OnPropertyChanged("IsAllValidated");
EnableButtonCommand.ChangeCanExecute();
}
}
This in the constructor for my ViewModel Class:
public Constructor()
{
EnableButtonCommand = new Command(EnableButton, () => !IsAllValidated);
}
My Validation-Class is setting the attributes to True after validation succeeds.
I worked with breakpoints and it looks like the IsAllValidated property is never updated--Only the 'Entry' properties are. Why is this happening, and what should I change?
IsAllValidated doesn't make much sense as a settable property, as it takes no value, and shouldn't need to store anything (since its state is wholly dependent on others', if I'm interpreting your requirements correctly). Instead, I would try something like this:
public bool IsAllValidated => IsValidatedEntry1 && IsValidatedEntry2;
I'm developing a Windows Forms app that has a lot of text and combo boxes which have to be entered manually. So there is a lot of checks if particular control is empty. I would like to get read of all validations in my UI and move them to the Middle Layer. This is great as UI is now validation free and exceptions are triggered as expected, but now I can't know which control causes exception to trigger. Well, I can, but not without intervention in my UI, which I obviously don't want, because this would make Middle layer validation unnecessary, as I could do it completely in UI. So, in short, what I would like to achieve is: if validation is triggered I would like to set focus to a control that causes exception, without focus hard setting in UI. Is this possible? Or if not, what would be the best solution? Any help appreciated.
I have created a simple example:
private void btnConfirm_Click(object sender, EventArgs e)
{
try
{
Customer.CustomerTN = txtCustomerTN.Text;
Customer.CustomerName = txtCustomerName.Text;
Customer.CustomerPhone = txtCustomerPhone.Text;
MessageBox.Show("Customer TN: " + Customer.CustomerTN +
Environment.NewLine +
"Customer Name: " + Customer.CustomerName +
Environment.NewLine +
"Customer Phone: " + Customer.CustomerPhone);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
//Middle Layer Class
public class Customer
{
private static string customerTN;
private static string customerName;
private static string customerPhone;
public static string CustomerTN
{
get
{
return customerTN;
}
set
{
if (value.Length == 0)
{
throw new Exception("Enter Customer TN...");
}
else
{
customerTN = value;
}
}
}
public static string CustomerName
{
get
{
return customerName;
}
set
{
if (value.Length == 0)
{
throw new Exception("Enter Customer Name...");
}
else
{
customerName = value;
}
}
}
public static string CustomerPhone
{
get
{
return customerPhone;
}
set
{
if (value.Length == 0)
{
throw new Exception("Enter Customer Phone...");
}
else
{
customerPhone = value;
}
}
}
}
You could create a hierarchy of Validation classes. Every Validation class would have a list of controls to validate. When the validation takes place, if the control doesn't complies with the rules, you can abort validation by showing up a message and giving focus to that control, e.g.:
public abstract class ControlValidator<T> where T : Control
{
protected List<T> ControlsToValidate;
public ControlValidator(IEnumerable<T> controls)
{
this.ControlsToValidate = new List<T>(controls);
}
public abstract bool ValidateControls();
}
Then, if you want a validator for text boxes you would create a validator like:
public class TextBoxValidator : ControlValidator<TextBox>
{
public TextBoxValidator(IEnumerable<TextBox> controls) : base(controls)
{}
public override bool ValidateControls()
{
foreach(TextBox tb in ControlsToValidate)
{
if (tb.Text == "") // This validates the text cannot be empty
{
MessageBox.Show("Text cannot be empty");
tb.Focus();
return false;
}
}
return True;
}
}
Then you would create a list of validators to store all the validators of your app:
List<ControlValidator> validators = ...
To validate all your controls you would do a foreach like:
foreach(var validator in validators)
{
if (!validator.ValidateControls())
break;
}
The foreach is interrupted once it finds out that at least one control wasn't successfully validated. Hope it helps.
Please consider that I have in an entity a property
public double RealVolume
{
get
{
return _RealVolume;
}
set
{
SetPropertyValue("RealVolume", ref _RealVolume, value);
}
}
then I also have
[Browsable(false)]
public VolumeType VolumeOrVolumePoints
{
get
{
return WMSSystemSetting.Get_VolumeOrVolumePoints(Session);
}
}
I want that when VolumeOrVolumePoints == VolumeType.Volume then RealVolume to be validated as an integer otherwise validated as double number.
How could I achieve this? Thanks!
For information on how to validate an object with XPO, see here. If you happen to be using DevExpress XAF then use a ValidationRule from the ValidationModule instead.
So you need something like:
protected override void OnSaving()
{
if (VolumeOrVolumePoints == VolumeType.Volume)
{
if (RealVolume % 1 != 0) // see http://stackoverflow.com/a/2751597/1077279
throw new Exception("The RealVolume value must be an integer when using Volume units.");
}
}
I have a WPF application that includes ~50 controls that are bound to properties on my business object which implements INotifyPropertyChanged. Here's a quick snippet of my business object:
public class MyBusinessObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
// properties begin here
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name == value)
{
return;
}
_name = value;
OnPropertyChanged(new PropertyChangedEventArgs("Name"));
}
}
// constructor, etc. not shown
}
I also have several validation rules that are used to validate the user input in these controls. I'm using command binding to prevent my user from saving the data if there are any validation errors. My application also includes a "Reset default values" button which, obviously, will reset the default value for all of the properties on my business object. This all works exactly as I'd like it to with one exception. If my user enters invalid data into one or more controls and then clicks the "Reset default values" button, the controls that contain invalid data don't always update as I'd expect. This happens because of the following code in my property setters:
if (_name == value)
{
return;
}
This code exists to prevent unnecessary property changed notifications from occurring when the value entered by my user in the bound UI control is the same value that the property is already set to. As an example, I have an IntegerUpDown control in my UI (this control is part of the Extended WPF Toolkit from Xceed). The default value of the property that my control is bound to is 10. My user deletes the value from the control and my validation rule is triggered which results in a validation error and the UI is updated appropriately with an error adorner, etc. The value of the property that this control is mapped to hasn't been changed so it's still set to 10. Now my user clicks the "Reset default values" button which will result in the default value (10) for the property being reset. However, the value for the property is already set to 10 so the short circuit logic in my setter will return instead of setting the property value.
So now, after my user clicks "Reset default values", I am also forcing an update on my binding target like this:
this.myIntegerUpDown.GetBindingExpression(Xceed.Wpf.Toolkit.IntegerUpDown.ValueProperty).UpdateTarget();
This solves my problem but only for this particular control. Is there any easy way to do this for all of my bound controls without having to specify each one? Thanks.
OnPropertyChanged(new PropertyChangedEventArgs(string.Empty));
This is intended to imply that ALL properties on that object have changed.
Could you do one of the following?
1) Reset the DataContext - Either recreate it, or re-set the property
var context = this.DataContext;
this.DataContext = null;
this.DataContext = context;
2) Loop through all properties programmatically via reflection and manually call OnPropertyChanged with the relevant property names.
var properties = typeof(ViewModel).GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var property in properties)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(property.Name));
}
You've mentioned validation and reset values, and of course the obvious one is to persist it.
Why don't you implement IEditableObject Interface on your entity that has three signature methods. BeginEdit(), CancelEdit() and EndEdit()
That way you can easily roll back your entity to the whatever you want, or validate it and lastly persist it. A good example is found here
Sample code
public class Customer : IEditableObject
{
struct CustomerData
{
internal string id ;
internal string firstName ;
internal string lastName ;
}
private CustomersList parent;
private CustomerData custData;
private CustomerData backupData;
private bool inTxn = false;
// Implements IEditableObject
void IEditableObject.BeginEdit()
{
Console.WriteLine("Start BeginEdit");
if (!inTxn)
{
this.backupData = custData;
inTxn = true;
Console.WriteLine("BeginEdit - " + this.backupData.lastName);
}
Console.WriteLine("End BeginEdit");
}
void IEditableObject.CancelEdit()
{
Console.WriteLine("Start CancelEdit");
if (inTxn)
{
this.custData = backupData;
inTxn = false;
Console.WriteLine("CancelEdit - " + this.custData.lastName);
}
Console.WriteLine("End CancelEdit");
}
void IEditableObject.EndEdit()
{
Console.WriteLine("Start EndEdit" + this.custData.id + this.custData.lastName);
if (inTxn)
{
backupData = new CustomerData();
inTxn = false;
Console.WriteLine("Done EndEdit - " + this.custData.id + this.custData.lastName);
}
Console.WriteLine("End EndEdit");
}
public Customer(string ID) : base()
{
this.custData = new CustomerData();
this.custData.id = ID;
this.custData.firstName = "";
this.custData.lastName = "";
}
public string ID
{
get
{
return this.custData.id;
}
}
public string FirstName
{
get
{
return this.custData.firstName;
}
set
{
this.custData.firstName = value;
this.OnCustomerChanged();
}
}
public string LastName
{
get
{
return this.custData.lastName;
}
set
{
this.custData.lastName = value;
this.OnCustomerChanged();
}
}
internal CustomersList Parent
{
get
{
return parent;
}
set
{
parent = value ;
}
}
private void OnCustomerChanged()
{
if (!inTxn && Parent != null)
{
Parent.CustomerChanged(this);
}
}
public override string ToString()
{
StringWriter sb = new StringWriter();
sb.Write(this.FirstName);
sb.Write(" ");
sb.Write(this.LastName);
return sb.ToString();
}
}
Wouldn't it be easier to just always call OnPropertyChanged regardless of whether its the same? How much of a performance boost does that give you?
i make user control from 3 text boxes but i don not how to declare read only property to it i tried many things but it do not work here is my code to make the control
i want to make it read only when needed like if i add checkbox i want if checkbox.check=true make my control readonly
public partial class dateIN : UserControl
{
Dates datess = new Dates();
public dateIN()
{
InitializeComponent();
}
private void dateIN_Leave(object sender, EventArgs e)
{
if (txtDay.Text != "" || txtMonth.Text != "" || txtYear.Text != "")
{
if (!datess.IsHijri(txtDay.Text.Trim() + "/" + txtMonth.Text.Trim() + "/" + txtYear.Text.Trim()))
{
txtDay.Focus();
}
}
}
public string Day
{
set { txtDay.Text = value; }
get { return txtDay.Text; }
}
public string Month
{
set { txtMonth.Text = value; }
get { return txtMonth.Text; }
}
public string Year
{
set { txtYear.Text = value; }
get { return txtYear.Text; }
}
need to know how to make read only property available here plz
just remove the set { } part of the property
Example:
public string Day
{
get { return txtDay.Text; }
}
I dont know the correlation of where your "txtDay", "txtMonth", "txtYear" come from, but you could do something like
public partial class dateIN : UserControl
{
...
...
private bool AllowEditing()
{ return SomeCondition when SHOULD be allowed...; }
public string Day
{
// only allow the set to apply the change if the "AllowEditing" condition
// is true, otherwise, ignore the attempt to assign.
set { if( AllowEditing() )
txtDay.Text = value; }
get { return txtDay.Text; }
}
// same concept for month and year too
}
so may you add some flag to your set when it is true then you set a value.
also you can work with textbox property called ReadOnly.