I what to sort table by field Order Number:Check List
I have a WrapperClass which implements interface Comparable:
public class CheckListWrapper implements Comparable
{
public Boolean isChecked {get; set;}
public String shortDescription {get; set;}
public String fullDescription {get; set;}
public Integer order {get; set;}
public CheckList__c checkList;
public CheckListItem__c checkListItem;
public CheckListWrapper(CheckList__c chList)
{
shortDescription = chList.Short_Description__c;
fullDescription = chList.Full_Description__c;
order = (Integer)chList.Order__c;
isChecked = false;
checkList = chList;
}
public CheckListWrapper(CheckListItem__c chListItem)
{
shortDescription = chListItem.CheckList__r.Short_Description__c;
fullDescription = chListItem.CheckList__r.Full_Description__c;
order = (Integer)chListItem.CheckList__r.Order__c;
isChecked = true;
checkListItem = chListItem;
}
public Integer compareTo(Object compareTo)
{
CheckListWrapper compareToCheckList = (CheckListWrapper)compareTo;
Integer returnValue = 0;
if (checkList != null)
{
if (checkList.Order__c > compareToCheckList.checkList.Order__c)
{
returnValue = 1;
} else if (checkList.Order__c < compareToCheckList.checkList.Order__c)
{
returnValue = -1;
}
} else if (checkListItem != null)
{
if (checkListItem.CheckList__r.Order__c > compareToCheckList.checkListItem.CheckList__r.Order__c)
{
returnValue = 1;
} else if (checkListItem.CheckList__r.Order__c < compareToCheckList.checkListItem.CheckList__r.Order__c)
{
returnValue = -1;
}
}
return returnValue;
}
}
Interface comparable works but all checked checkboxes are higher than unchecked.
The question is why checked checkboxes are higher than unchecked and how could be avoided it?
Well. I understood my mistake: Everything is alright, but I had should used one block if else in the method compareTo and don't reference to field Order__c through the Object CheckList__c. I had should used "order" variable from CheckListWrapper:
public Integer compareTo(Object compareTo)
{
CheckListWrapper compareToCheckList = (CheckListWrapper)compareTo;
Integer returnValue = 0;
if (order > compareToCheckList.order)
{
returnValue = 1;
} else if (order < compareToCheckList.order)
{
returnValue = -1;
}
return returnValue;
}
Related
Hi am struggling with validation with data annotations in WPF
I have a class in a separate project because we are reusing the class across multiple projects.Several of the fields have data annotations for validation.
the validation class combines the errors returned from data annotations with some custom business rules which are different per client
internal class Validation<T> : ValidationRule where T : class, ICore
{
IUnitofWork unitofWork;
List<Func<T, bool>> CompiledRules = new List<Func<T, bool>>();
List<Rule<T>> Rules = new List<Rule<T>>();
Dictionary<string, List<string>> _errors = new Dictionary<string, List<string>>();
List<Func<Object, bool>> FieldRules = new List<Func<object, bool>>();
public Validation()
{
unitofWork = new UnitOfWork();
CompileRules();
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
return IsValid((T)value);
}
public ValidationResult Validate(object value,string PropertyName ,CultureInfo cultureInfo)
{
return IsValid((T)value,PropertyName);
}
void CompileRules()
{
Type t = typeof(T);
List<BusinessRule> rules = unitofWork.Repository<BusinessRule>().GetAll(b => b.Name == t.Name && b.Enabled == true);
foreach (BusinessRule b in rules)
{
Func<T, bool> CompiledRule = CompileRule(b);
CompiledRules.Add(CompiledRule);
Rule<T> rule = new Rule<T>();
rule.CompiledRule = CompiledRule;
rule.ErrorMessage = b.MessageTemplate;
rule.FieldName = b.Field;
Rules.Add(rule);
}
}
ValidationResult IsValid(T Value)
{
bool valid = true;
_errors.Clear();
if (CompiledRules.Count > 0 || Value.Errors.Count > 0)
{
//valid = CompiledRules.All(rule => rule(Value));
foreach (Rule<T> r in Rules)
{
bool isValid = r.CompiledRule(Value);
r.PassedRule = isValid;
string field = r.FieldName;
if (!isValid )
{
valid = false;
string ErrorMessage = string.Format("{0} {1}", r.FieldName, r.ErrorMessage);
if (_errors.ContainsKey(field))
_errors[field].Add(ErrorMessage);
else
{
List<string> el = new List<string>();
el.Add(ErrorMessage);
_errors.Add(field, el);
}
}
}
}
ValidateAnnotations(Value,ref valid);
return new ValidationResult(valid, _errors);
}
void ValidateAnnotations(object Value,ref bool Valid)
{
DataAnnotationValidator annotationValidator = new DataAnnotationValidator();
List< System.ComponentModel.DataAnnotations.ValidationResult> results = annotationValidator.ValidateObject(Value);
if (results.Count > 0)
{
Valid = false;
foreach (System.ComponentModel.DataAnnotations.ValidationResult r in results)
{
if (_errors.ContainsKey(r.MemberNames.First()))
{
_errors[r.MemberNames.First()].Add(r.ErrorMessage);
}
else
{
List<string> propErrors = new List<string>();
propErrors.Add(r.ErrorMessage);
_errors.Add(r.MemberNames.First(), propErrors);
}
}
}
}
void ValidateAnnotations(object Value,string PropertyName, ref bool Valid)
{
DataAnnotationValidator annotationValidator = new DataAnnotationValidator();
List<System.ComponentModel.DataAnnotations.ValidationResult> results = annotationValidator.ValidateObject(Value, PropertyName);
if (results.Count > 0)
{
Valid = false;
foreach (System.ComponentModel.DataAnnotations.ValidationResult r in results)
{
if (_errors.ContainsKey(r.MemberNames.First()))
{
_errors[r.MemberNames.First()].Add(r.ErrorMessage);
}
else
{
List<string> propErrors = new List<string>();
propErrors.Add(r.ErrorMessage);
_errors.Add(r.MemberNames.First(), propErrors);
}
}
}
}
ValidationResult IsValid(T Value, string PropertyName)
{
_errors.Remove(PropertyName);
bool valid = true;
if (CompiledRules.Count > 0)
{
//valid = CompiledRules.All(rule => rule(Value));
foreach (Rule<T> r in Rules.Where(b=>b.FieldName == PropertyName))
{
bool isValid = r.CompiledRule(Value);
r.PassedRule = isValid;
string field = r.FieldName;
// string field = "SelectedRow." + r.FieldName;
if (!isValid)
{
valid = false;
string ErrorMessage = string.Format("{0} {1}", r.FieldName, r.ErrorMessage);
if (_errors.ContainsKey(field))
_errors[field].Add(ErrorMessage);
else
{
List<string> el = new List<string>();
el.Add(ErrorMessage);
_errors.Add(field, el);
}
}
}
}
ValidateAnnotations(Value,PropertyName, ref valid);
return new ValidationResult(valid, _errors);
}
public Func<T, bool> CompileRule(BusinessRule r)
{
var paramT = Expression.Parameter(typeof(T));
Expression expression = BuildExpr(r, paramT);
return Expression.Lambda<Func<T, bool>>(expression, paramT).Compile();
}
static Expression BuildExpr(BusinessRule r, ParameterExpression param)
{
var left = MemberExpression.Property(param, r.Field);
var tProp = typeof(T).GetProperty(r.Field).PropertyType;
ExpressionType tBinary;
// is the operator a known .NET operator?
if (ExpressionType.TryParse(r.Operator, out tBinary))
{
var right = Expression.Constant(Convert.ChangeType(r.CompareValue, tProp));
// use a binary operation, e.g. 'Equal' -> 'u.Age == 15'
return Expression.MakeBinary(tBinary, left, right);
}
else
{
var method = tProp.GetMethod(r.Operator);
var tParam = method.GetParameters()[0].ParameterType;
var right = Expression.Constant(Convert.ChangeType(r.CompareValue, tParam));
// use a method call, e.g. 'Contains' -> 'u.Tags.Contains(some_tag)'
return Expression.Call(left, method, right);
}
}
}
internal class Rule<T> where T : class, ICore
{
public string FieldName
{ get;set; }
public Func<T, bool> CompiledRule
{ get; set; }
public Func<object,bool> RevisedRule
{ get; set; }
public string ErrorMessage
{ get; set; }
public bool PassedRule
{ get; set; }
}
internal class Error
{
public string ErrorMessage { get; set; }
public string FieldName { get; set; }
}
The is working as the _errors list has the field names and any errors associated with them.
once we have these we loop through and raise the onPropertyErrorsChangedEvent
internal void SetErrorDetails(ValidationResult Result)
{
propErrors = (Dictionary<string, List<string>>)Result.ErrorContent;
foreach (string key in propErrors.Keys)
{
OnPropertyErrorsChanged(key);
}
}
on my view the 2 fields are
<TextBox Canvas.Left="138"
Canvas.Top="75"
FontFamily="Verdana"
HorizontalAlignment="Left"
Height="20"
Text="{Binding OrganizationName,ValidatesOnDataErrors=True,NotifyOnValidationError=True,ValidatesOnNotifyDataErrors=True,ValidatesOnExceptions=True}" VerticalAlignment="Top" Width="137"
Validation.ErrorTemplate="{StaticResource ValidationTemplate }"
Style="{StaticResource TextErrorStyle}"/>
<TextBox Canvas.Left="138"
Canvas.Top="225"
FontFamily="Verdana"
HorizontalAlignment="Left"
Height="20"
Text="{Binding SelectedRow.Postcode,ValidatesOnDataErrors=True,ValidatesOnNotifyDataErrors=True,ValidatesOnExceptions=True}"
VerticalAlignment="Top"
Width="137"
Validation.ErrorTemplate="{StaticResource ValidationTemplate }"
Style="{StaticResource TextErrorStyle}" />
I am encountering 2 problems i am encountering
When bound directly to the selectedrow (Postcode) my data annotations appear when the form is loaded but when bound via a field on my view model (Organisation Name) they do not . We need to bind these to fields on the view model so that the business rules get run as part of validation.
Second problem if i save the form with an invalid entry for the organisation the save stops because it is invalid however i don't get an error notification even though there is an error for the property in the _errors.
I am not sure what i am doing wrong could someone point me in the right direction please?
[Edit]
We use a third party document service to create and show the view
void CreateDocument(object Arg)
{
string title = string.Empty;
if (Arg.ToString().ToLower() == "edit" && SelectedRow !=null)
{
if (SelectedRow.OrganizationName != null)
title = SelectedRow.OrganizationName;
}
else
{
SelectedRow = new Address();
title = "New Address";
}
AddressDetailVM detail = new AddressDetailVM(SelectedRow,this);
Document = iInternal.CreateDocument("AddressDetails",
detail,
title
);
detail.Document = Document;
// Document = iInternal.CreateDocument("AddressDetails", null, this, title);
Document.Show();
}
I am trying to get list of Tbcompany table using Transformers.aliasToBean with 2 primary key fields.
I am using SQL SERVER and Hibernate 3.2.4.
My table has 2 primary fields.
Tbcompany.class
public class Tbcompany {
private TbcompanyId id;
private String hcompanycode;
public TbcompanyId getId() {
return id;
}
public void setId(TbcompanyId id) {
this.id = id;
}
public String getHcompanycode() {
return hcompanycode;
}
public void setHcompanycode(String hcompanycode) {
this.hcompanycode = hcompanycode;
}
}
And inside TbcompanyId.class :
public class TbcompanyId
implements Serializable
{
private String companycode;
private String companyname;
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (!(o instanceof TbcompanyId)) {
return false;
}
TbcompanyId other = ((TbcompanyId) o);
if (this.companycode == null) {
if (other.companycode!= null) {
return false;
}
} else {
if (!this.companycode.equals(other.companycode)) {
return false;
}
}
if (this.companyname == null) {
if (other.companyname!= null) {
return false;
}
} else {
if (!this.companyname.equals(other.companyname)) {
return false;
}
}
return true;
}
public int hashCode() {
int rtn = 17;
rtn = (rtn* 37);
if (this.companycode!= null) {
rtn = (rtn + this.companycode.hashCode());
}
rtn = (rtn* 37);
if (this.companyname!= null) {
rtn = (rtn + this.companyname.hashCode());
}
return rtn;
}
public String getCompanycode() {
return companycode;
}
public void setCompanycode(String companycode) {
this.companycode = companycode;
}
public String getCompanyname() {
return companyname;
}
public void setCompanyname(String companyname) {
this.companyname = companyname;
}
I want to create a form and use Transformers.aliasToBean to populate the form .
This query :
Query q;
q = session.createQuery("SELECT a.id.companycode as companycode,a.id.companyname as companyname,a.hcompanycode as hcompanycode FROM Tbcompany a");
q.setResultTransformer(Transformers.aliasToBean(Tbcompany.class));
list = q.list();
gives me an error of :
org.hibernate.PropertyNotFoundException: Could not find setter for companycode on class com.loansdb.data.Tbcompany
While this query :
Query q;
q = session.createQuery("SELECT a.id.companycode,a.id.companyname,a.hcompanycode as hcompanycode FROM
Tbcompany a");
q.setResultTransformer(Transformers.aliasToBean(Tbcompany.class));
list = q.list();
gives me this error :
org.hibernate.PropertyNotFoundException: Could not find setter for 0 on class com.loansdb.data.Tbcompany
Does anyone know how to do this?
The aliasToBean transformer use the name of the SQL columns returned and try to find a field with the same name on the class target that have a set method created.
So, your query returns a a.id.companycode:
SELECT a.id.companycode as companycode,a.id.companyname as companyname,a.hcompanycode as hcompanycode FROM Tbcompany a
The error said:
org.hibernate.PropertyNotFoundException: Could not find setter for companycode on class com.loansdb.data.Tbcompany
And your Tbcompany class does not have a setter to companycode.
So, to correct your Tbcompany class and looking your query, seems to me that the class it's something like:
public class Tbcompany {
private String companycode;
private String companycode;
private String companyname;
public String setCompanycode(String companycode) {
this.companycode = companycode;
}
// create the constructor, getters and setters
}
as the topic suggests I wan't to modify the Content of the CollectionEditorPicker. This control is used to open the floating Window for the List of nested Properties.
Unfortunally the RadPropertyGrid don't show any Information about the collection in the Field.
How can I set some value in there? For example a placeholder like "Click here to open the collection" or "xx Items" or "Item 1, Item 2, Item 3..." so see some preview or Information about the field.
I've tried it with a template Selector, but if I'm doing so, the opened Popup is not resizable anymore. Also it looses some Information which are in the default CollectionEditorPicker.
Can you help me?
Below a minimal working Example.
The XAML:
<Window x:Class="TelerikPropertyGridTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:model="clr-namespace:TelerikPropertyGridTest.Model"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<model:TemplateSelector x:Key="RadPropertyListTemplateSelector">
<!-- Not Working -->
<model:TemplateSelector.CollectionsDataTemplate>
<DataTemplate>
<telerik:RadDropDownButton Content="Test">
<telerik:RadDropDownButton.DropDownContent>
<telerik:CollectionEditor telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Source"
></telerik:CollectionEditor>
</telerik:RadDropDownButton.DropDownContent>
</telerik:RadDropDownButton>
</DataTemplate>
</model:TemplateSelector.CollectionsDataTemplate>
<model:TemplateSelector.FloatNumberTemplate>
<DataTemplate>
<telerik:RadNumericUpDown telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Value" />
</DataTemplate>
</model:TemplateSelector.FloatNumberTemplate>
<model:TemplateSelector.IntNumberTemplate>
<DataTemplate>
<telerik:RadNumericUpDown telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Value"
NumberDecimalDigits="0" />
</DataTemplate>
</model:TemplateSelector.IntNumberTemplate>
</model:TemplateSelector>
</Grid.Resources>
<telerik:RadPropertyGrid Item="{Binding ObjectToBind}"
AutoGeneratingPropertyDefinition="RadPropertyGrid_OnAutoGeneratingPropertyDefinition"
EditorTemplateSelector="{StaticResource RadPropertyListTemplateSelector}">
</telerik:RadPropertyGrid>
</Grid>
</Window>
The ViewModel (generates a Random Object for testing)
public class MainWindowViewModel : BindableBase
{
private readonly Random _random = new Random();
private IExampleInterface _objectToBind;
public MainWindowViewModel()
{
this.ObjectToBind = new ExampleImplementation
{
SomeBooleanValue = this._random.Next() % 2 == 1,
SomeDateValue = this.RandomDay(),
SomeIntValue = this._random.Next(),
SomeString = Guid.NewGuid().ToString(),
SubClasses = new List<IExampleInterface>
{
new ExampleImplementation
{
SomeBooleanValue = this._random.Next() % 2 == 1,
SomeDateValue = this.RandomDay(),
SomeIntValue = this._random.Next(),
SomeString = Guid.NewGuid().ToString(),
SubClasses = new List<IExampleInterface>
{
new ExampleImplementation
{
SomeBooleanValue =
this._random.Next() % 2 == 1,
SomeDateValue = this.RandomDay(),
SomeIntValue = this._random.Next(),
SomeString = Guid.NewGuid().ToString()
}
}
}
}
};
}
public IExampleInterface ObjectToBind
{
get { return this._objectToBind; }
set
{
if (this._objectToBind != value)
{
this._objectToBind = value;
this.OnPropertyChanged("ObjectToBind");
}
}
}
private DateTime RandomDay()
{
var start = new DateTime(1995, 1, 1);
var range = (DateTime.Today - start).Days;
return start.AddDays(this._random.Next(range));
}
}
The IExampleInterface (should be later on a real Interface):
public interface IExampleInterface
{
string SomeString { get; set; }
int SomeIntValue { get; set; }
double SomeDouble { get; set; }
IList<IExampleInterface> SubClasses { get; set; }
IList<IExampleInterface> SubClasses2 { get; set; }
bool SomeBooleanValue { get; set; }
DateTime SomeDateValue { get; set; }
SomeEnum SomeEnumValue { get; set; }
}
The ExampleImplementation (should have later on a Real Implementation with additional Properties).
public class ExampleImplementation : BindableBase, IExampleInterface
{
private bool _someBooleanValue;
private DateTime _someDateValue;
private double _someDouble;
private SomeEnum _someEnumValue;
private int _someIntValue;
private string _someString;
private ObservableCollection<IExampleInterface> _subClasses;
private ObservableCollection<IExampleInterface> _subClasses2;
public bool SomeBooleanValue
{
get { return this._someBooleanValue; }
set
{
if (this._someBooleanValue != value)
{
this._someBooleanValue = value;
this.OnPropertyChanged("SomeBooleanValue");
}
}
}
public DateTime SomeDateValue
{
get { return this._someDateValue; }
set
{
if (this._someDateValue != value)
{
this._someDateValue = value;
this.OnPropertyChanged("SomeDateValue");
}
}
}
public double SomeDouble
{
get { return this._someDouble; }
set
{
if (Math.Abs(this._someDouble - value) > 0.01)
{
this._someDouble = value;
this.OnPropertyChanged("SomeDouble");
}
}
}
public SomeEnum SomeEnumValue
{
get { return this._someEnumValue; }
set
{
if (this._someEnumValue != value)
{
this._someEnumValue = value;
this.OnPropertyChanged("SomeEnumValue");
}
}
}
public int SomeIntValue
{
get { return this._someIntValue; }
set
{
if (this._someIntValue != value)
{
this._someIntValue = value;
this.OnPropertyChanged("SomeIntValue");
}
}
}
[Display(Name = #"TestString", GroupName = #"TestGroup", Description = #"TestDescription")]
public string SomeString
{
get { return this._someString; }
set
{
if (this._someString != value)
{
this._someString = value;
this.OnPropertyChanged("SomeString");
}
}
}
[Display(Name = #"Some Subclasses")]
public IList<IExampleInterface> SubClasses
{
get { return this._subClasses; }
set
{
if (!Equals(this._subClasses, value))
{
this._subClasses = new ObservableCollection<IExampleInterface>(value);
this.OnPropertyChanged("SubClasses");
}
}
}
public IList<IExampleInterface> SubClasses2
{
get { return this._subClasses2; }
set
{
if (!Equals(this._subClasses2, value))
{
this._subClasses2 = new ObservableCollection<IExampleInterface>(value);
this.OnPropertyChanged("SubClasses2");
}
}
}
}
And finally the TemplateSelector
public class TemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var def = item as PropertyDefinition;
if (def == null || def.SourceProperty == null)
{
return base.SelectTemplate(item, container);
}
if (typeof (IEnumerable).IsAssignableFrom(def.SourceProperty.PropertyType) && typeof(string) != def.SourceProperty.PropertyType)
{
return this.CollectionsDataTemplate;
}
if (typeof (double).IsAssignableFrom(def.SourceProperty.PropertyType))
{
return this.FloatNumberTemplate;
}
if (typeof (int).IsAssignableFrom(def.SourceProperty.PropertyType))
{
return this.IntNumberTemplate;
}
return base.SelectTemplate(item, container);
}
public DataTemplate CollectionsDataTemplate { get; set; }
public DataTemplate FloatNumberTemplate { get; set; }
public DataTemplate IntNumberTemplate { get; set; }
}
This is what I expect
The optimal solution would be to get detailed Information in the TextBlock, like Item 1, item 2 etc.
Thank you.
// Edit:
I've figured out the NullReferenceException and got a Demo to work, so that I can modify the text. But the popup is different to the default. Have you an idea to fix it?
I've updated the text and the example.
After wasting a few hours now I figured out a solution to realize this.
I've added a custom behavior to the Collection template. This behavior sets the Header of the CollectionEditor as soon as it's loaded or updated.
Below you can see my modifications:
The Template:
<model:TemplateSelector.CollectionsDataTemplate>
<DataTemplate>
<telerik:RadDropDownButton Content="Click to edit the collection">
<telerik:RadDropDownButton.DropDownContent>
<telerik:CollectionEditor telerik:AutoBindBehavior.UpdateBindingOnElementLoaded="Source"
ResizeGripperVisibility="Visible">
<i:Interaction.Behaviors>
<model:CollectionEditorBehavior />
</i:Interaction.Behaviors>
</telerik:CollectionEditor>
</telerik:RadDropDownButton.DropDownContent>
</telerik:RadDropDownButton>
</DataTemplate>
</model:TemplateSelector.CollectionsDataTemplate>
The behavior:
internal class CollectionEditorBehavior : Behavior<CollectionEditor>
{
protected override void OnAttached()
{
this.AssociatedObject.SourceUpdated += (sender, args) => this.PrepareHeader();
this.AssociatedObject.DataContextChanged += (sender, args) => this.PrepareHeader();
this.AssociatedObject.Loaded += (sender, args) => this.PrepareHeader();
}
private void PrepareHeader()
{
if (this.AssociatedObject == null)
{
// Error Case
return;
}
if (this.AssociatedObject.CollectionView == null ||
this.AssociatedObject.CollectionView.SourceCollection == null)
{
// Source not set
this.AssociatedObject.Header = "Collection";
return;
}
// Get the property from the DataContext to retrieve HeaderInformation
var propInfo = this.AssociatedObject.DataContext
.GetType()
.GetProperties()
.FirstOrDefault(
propertyInfo =>
Equals(propertyInfo.GetValue(this.AssociatedObject.DataContext),
this.AssociatedObject.CollectionView.SourceCollection));
if (propInfo == null)
{
// We didn't got the property Information, using default value
this.AssociatedObject.Header = "Collection";
return;
}
// Getting the DisplayName Attribute
var attr = Attribute.GetCustomAttribute(propInfo,
typeof (DisplayNameAttribute)) as DisplayNameAttribute;
if (attr != null)
{
// We have a DisplayName attribute
this.AssociatedObject.Header = attr.DisplayName;
return;
}
// Alternative: Get the Display Attribute
var attr2 = Attribute.GetCustomAttribute(propInfo,
typeof (DisplayAttribute)) as DisplayAttribute;
if (attr2 != null)
{
// We have the Display Attribute
this.AssociatedObject.Header = attr2.Name;
return;
}
// We have no DisplayAttribute and no DisplayName attribute, set it to the PropertyName
this.AssociatedObject.Header = propInfo.Name;
}
}
I am throwing some custom exceptions in my controller and I'm noticing when there are multiple errors, the errors do not display all at once. Rather they display one at a time on the page. I'm using the pageMessages component.
I think the issue is in the controller on how I'm adding the errors in the catch block for all the different methods.
Here is my class:
public with sharing class CallReportControllerExtension {
private Call_Report__c callReport;
public Boolean isEditMode {get; set;}
public List<Participants> participantLinesForPage {get; set;}
public List<ProductsPresented> productLinesForPage {get; set;}
public List<Tasks> taskLinesForPage {get; set;}
public CallReportControllerExtension(ApexPages.StandardController stdController) {
this.callReport = (Call_Report__c)stdController.getRecord();
isEditMode = isEditPage(ApexPages.currentPage().getParameters().get('save_new'));
refreshParticipantLineItems();
refreshProductLineItems();
refreshTaskLineItems();
}
public PageReference save() {
Savepoint sp = Database.setSavepoint();
try {
insert callReport;
upsertParticipants(callReport.Id);
upsertProducts(callReport.Id);
upsertTasks(callReport.Id);
}
catch(Exception ex) {
ApexPages.addMessages(ex);
Database.rollback(sp);
callReport = callReport.clone(false);
return null;
}
PageReference pageRef = new ApexPages.StandardController(callReport).view();
pageRef.setRedirect(true);
return pageRef;
}
public PageReference updateCallReport() {
Savepoint sp = Database.setSavepoint();
try {
update callReport;
upsertParticipants(callReport.Id);
upsertProducts(callReport.Id);
upsertTasks(callReport.Id);
}
catch(Exception ex) {
ApexPages.addMessages(ex);
Database.rollback(sp);
return null;
}
PageReference pageRef = new ApexPages.StandardController(callReport).view();
pageRef.setRedirect(true);
return pageRef;
}
private PageReference upsertParticipants(String callreportid) {
List<Participant__c> recordsToUpsert = new List<Participant__c>();
for(Participants parts : participantLinesForPage) {
if(parts.participantLine.Call_Report__c == null) {
Participant__c p = new Participant__c();
p.Call_Report__c = callreportid;
if(!String.isEmpty(parts.accountId)) {
p.Account__c = parts.accountId;
} else {
p.Account__c = null;
}
if(!String.isEmpty(parts.contactId)) {
p.Contact__c = parts.contactId;
} else {
p.Contact__c = null;
}
if(!String.isEmpty(parts.userId)) {
p.User__c = parts.userId;
} else {
p.User__c = null;
}
recordsToUpsert.add(p);
}
else {
if(!String.isEmpty(parts.accountId)) {
parts.participantLine.Account__c = parts.accountId;
} else {
parts.participantLine.Account__c = null;
}
if(!String.isEmpty(parts.contactId)) {
parts.participantLine.Contact__c = parts.contactId;
} else {
parts.participantLine.Contact__c = null;
}
if(!String.isEmpty(parts.userId)) {
parts.participantLine.User__c = parts.userId;
} else {
parts.participantLine.User__c = null;
}
recordsToUpsert.add(parts.participantLine);
}
}
if(!recordsToUpsert.isEmpty() && recordsToUpsert.size() > 0) {
try {
upsert recordsToUpsert;
}
catch(Exception ex) {
ApexPages.addMessages(ex);
return null;
}
}
return null;
}
private PageReference upsertProducts(String callreportid) {
List<Products_Presented__c> recordsToUpsert = new List<Products_Presented__c>();
for(ProductsPresented prodPresented : productLinesForPage) {
if(prodPresented.productLine.Call_Report__c == null) {
Products_Presented__c pp = new Products_Presented__c();
pp.Call_Report__c = callreportid;
if(!String.isEmpty(prodPresented.productId)) {
pp.Product__c = prodPresented.productId;
} else {
throw new CallReportException('The Product presented field is blank. Please select a product.');
}
pp.Notes__c = prodPresented.productLine.Notes__c;
pp.At_Risk__c = prodPresented.productLine.At_Risk__c;
recordsToUpsert.add(pp);
}
else {
if(!String.isEmpty(prodPresented.productId)) {
prodPresented.productLine.Product__c = prodPresented.productId;
} else {
throw new CallReportException('The Product presented field is blank. Please select a product.');
}
prodPresented.productLine.Notes__c = prodPresented.productLine.Notes__c;
prodPresented.productLine.At_Risk__c = prodPresented.productLine.At_Risk__c;
recordsToUpsert.add(prodPresented.productLine);
}
}
if(!recordsToUpsert.isEmpty() && recordsToUpsert.size() > 0) {
try {
upsert recordsToUpsert;
}
catch(Exception ex) {
ApexPages.addMessages(ex);
return null;
}
}
return null;
}
private PageReference upsertTasks(String callreportid) {
List<Task> recordsToUpsert = new List<Task>();
for(Tasks t : taskLinesForPage) {
if(t.taskLine.WhatId == null) {
Task task = new Task();
task.WhatId = callreportid;
if(!String.isEmpty(t.whoId)) {
task.WhoId = t.whoId;
} else {
task.WhoId = null;
}
if(String.isEmpty(t.userId)) throw new CallReportException('The Assigned To field is blank. Please select a user that is assigned this task.');
task.OwnerId = t.userId;
task.Subject = 'Call Report Task';
task.ActivityDate = t.taskLine.ActivityDate;
task.Description = t.taskLine.Description;
task.Status = 'Not Started';
task.Priority = 'Normal';
recordsToUpsert.add(task);
}
else {
if(!String.isEmpty(t.whoId)) {
t.taskLine.WhoId = t.whoId;
} else {
t.taskLine.WhoId = null;
}
if(String.isEmpty(t.userId)) throw new CallReportException('The Assigned To field is blank. Please select a user that is assigned this task.');
t.taskLine.OwnerId = t.userId;
t.taskLine.ActivityDate = t.taskLine.ActivityDate;
t.taskLine.Description = t.taskLine.Description;
recordsToUpsert.add(t.taskLine);
}
}
if(!recordsToUpsert.isEmpty() && recordsToUpsert.size() > 0) {
try {
upsert recordsToUpsert;
}
catch(Exception ex) {
ApexPages.addMessages(ex);
return null;
}
}
return null;
}
public PageReference addParticipant() {
Participant__c newRecord = new Participant__c();
participantLinesForPage.add(new Participants(participantLinesForPage.size(), newRecord, newRecord.Account__r.Id, newRecord.Account__r.Name, newRecord.Contact__r.Id, newRecord.Contact__r.Name, newRecord.User__r.Id, newRecord.User__r.Name));
return null;
}
public PageReference deleteParticipant() {
Integer selectId = Integer.valueOf(ApexPages.currentPage().getParameters().get('del'));
Participants toRemove = participantLinesForPage.get(selectId);
try {
if(toRemove.participantLine.Id != null) {
delete [select Id from Participant__c where Id =: toRemove.ParticipantLine.Id];
}
participantLinesForPage.remove(selectId);
} catch (Exception e) {
ApexPages.addMessages(e);
}
Integer iterate = 0;
for(Participants parts : participantLinesForPage) {
parts.iterate = iterate;
iterate +=1;
}
return null;
}
public PageReference addProduct() {
Products_Presented__c newRecord = new Products_Presented__c();
productLinesForPage.add(new ProductsPresented(productLinesForPage.size(), newRecord, newRecord.Product__r.Id, newRecord.Product__r.Name));
return null;
}
public PageReference deleteProduct() {
Integer selectId = Integer.valueOf(ApexPages.currentPage().getParameters().get('del'));
ProductsPresented toRemove = productLinesForPage.get(selectId);
try {
if(toRemove.productLine.Id != null) {
delete [select Id from Products_Presented__c where Id =: toRemove.productLine.Id];
}
productLinesForPage.remove(selectId);
} catch (Exception e) {
ApexPages.addMessages(e);
}
Integer iterate = 0;
for(ProductsPresented prods : productLinesForPage) {
prods.iterate = iterate;
iterate +=1;
}
return null;
}
public PageReference addTask() {
Task newRecord = new Task();
taskLinesForPage.add(new Tasks(taskLinesForPage.size(), newRecord, newRecord.Who.Id, newRecord.Who.Name, newRecord.Owner.Id, newRecord.Owner.Name));
return null;
}
public PageReference deleteTask() {
Integer selectId = Integer.valueOf(ApexPages.currentPage().getParameters().get('del'));
Tasks toRemove = taskLinesForPage.get(selectId);
try {
if(toRemove.taskLine.Id != null) {
delete [select Id from Task where Id =: toRemove.taskLine.Id];
}
taskLinesForPage.remove(selectId);
} catch (Exception e) {
ApexPages.addMessages(e);
}
Integer iterate = 0;
for(Tasks tasks : taskLinesForPage) {
tasks.iterate = iterate;
iterate +=1;
}
return null;
}
private void refreshParticipantLineItems() {
List<Participant__c> lineItems = [select Account__c, Account__r.Id, Account__r.Name, Contact__c, Contact__r.Id, Contact__r.Name, User__c, User__r.Id, User__r.Name, Spent_Amount__c, Call_Report__c from Participant__c where Call_Report__c =: callReport.Id];
participantLinesForPage = new List<Participants>();
Integer iterate = 0;
for(Participant__c p : lineItems) {
participantLinesForPage.add(new Participants(iterate, p, String.valueOf(p.Account__r.Id), p.Account__r.Name, String.valueOf(p.Contact__r.Id), p.Contact__r.Name, String.valueOf(p.User__r.Id), p.User__r.Name));
iterate += 1;
}
}
private void refreshProductLineItems() {
List<Products_Presented__c> prodsPresentedLineItems = [select Product__r.Id, Product__r.Name, Call_Report__c, Notes__c, At_Risk__c from Products_Presented__c where Call_Report__c =: callReport.Id];
productLinesForPage = new List<ProductsPresented>();
Integer iterate = 0;
for(Products_Presented__c pp : prodsPresentedLineItems) {
productLinesForPage.add(new ProductsPresented(iterate, pp, String.valueOf(pp.Product__r.Id), pp.Product__r.Name));
iterate += 1;
}
}
private void refreshTaskLineItems() {
List<Task> taskLineItems = new List<Task>();
if(callReport.Id != null) {
taskLineItems = [select Who.Id, Who.Name, ActivityDate, Description, WhatId, OwnerId, Owner.Id, Owner.Name from Task where WhatId =: callReport.Id];
}
taskLinesForPage = new List<Tasks>();
Integer iterate = 0;
for(Task t : taskLineItems) {
taskLinesForPage.add(new Tasks(iterate, t, String.valueOf(t.Who.Id), t.Who.Name, String.valueOf(t.Owner.Id), t.Owner.Name));
iterate += 1;
}
}
private Boolean isEditPage(String param) {
Boolean retval = true;
if(param != null) {
retval = false;
}
return retval;
}
class Participants {
public Integer iterate {get; set;}
public Participant__c participantLine {get; set;}
public String accountId {get; set;}
public String accountName {get; set;}
public String contactId {get; set;}
public String contactName {get; set;}
public String userId {get; set;}
public String userName {get; set;}
public Participants(Integer iterate, Participant__c participantLine, String accountId, String accountName, String contactId, String contactName, String userId, String userName) {
this.iterate = iterate;
this.participantLine = participantLine;
this.accountId = accountId;
this.accountName = accountName;
this.contactId = contactId;
this.contactName = contactName;
this.userId = userId;
this.userName = userName;
}
}
class ProductsPresented {
public Integer iterate {get; set;}
public Products_Presented__c productLine {get; set;}
public String productId {get; set;}
public String productName {get; set;}
public ProductsPresented(Integer iterate, Products_Presented__c productLine, String productId, String productName) {
this.iterate = iterate;
this.productLine = productLine;
this.productId = productId;
this.productName = productName;
}
}
class Tasks {
public Integer iterate {get; set;}
public Task taskLine {get; set;}
public String whoId {get; set;}
public String whoName {get; set;}
public String userId {get; set;}
public String userName {get; set;}
public Tasks(Integer iterate, Task taskLine, String whoId, String whoName, String userId, String userName) {
this.iterate = iterate;
this.taskLine = taskLine;
this.whoId = whoId;
this.whoName = whoName;
this.userId = userId;
this.userName = userName;
}
}
}
Thanks for any help.
For example you have four DML operations and the first operation falls, so the code does not continue to the second operation. So you only displays the first error on the page.
try {
action 1;
action 2;
action 3;
action 4;
} catch(Exception ex) {
ApexPages.addMessages(ex);
}
If it necessary you can change it to something like this.
try { action 1;}catch(exception ex){ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,ex.getMessage()));}
try { action 2;}catch(exception ex){ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,ex.getMessage()));}...
if(ApexPages.hasMessages())return null;
I followed Trouble saving a collection of objects in Application Settings to save my ObservableCollection of custom objects which is bound to a DataGrid in the application settings, but the data is not stored in user.config like the other settings.
Can somebody help me with this?
Thank you!
My custom classes:
[Serializable()]
public class ActuatorParameter
{
public ActuatorParameter()
{}
public string caption { get; set; }
public int value { get; set; }
public IntRange range { get; set; }
public int defaultValue { get; set; }
}
and
[Serializable()]
public class IntRange
{
public int Max { get; set; }
public int Min { get; set; }
public IntRange(int min, int max)
{
Max = max;
Min = min;
}
public bool isInRange(int value)
{
if (value < Min || value > Max)
return true;
else
return false;
}
}
Fill collection and save:
Settings.Default.pi_parameters = new ObservableCollection<ActuatorParameter>
{
new ActuatorParameter() { caption = "Velocity", range = new IntRange(1, 100000), defaultValue = 90000},
new ActuatorParameter() { caption = "Acceleration", range = new IntRange(1000, 1200000), defaultValue = 600000},
new ActuatorParameter() { caption = "P-Term", range = new IntRange(150, 350), defaultValue = 320},
new ActuatorParameter() { caption = "I-Term", range = new IntRange(0, 60), defaultValue = 30},
new ActuatorParameter() { caption = "D-Term", range = new IntRange(0, 1200), defaultValue = 500},
new ActuatorParameter() { caption = "I-Limit", range = new IntRange(0, 1000000), defaultValue = 2000}
};
Settings.Default.Save();
My custom setting:
internal sealed partial class Settings
{
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
public ObservableCollection<ActuatorParameter> pi_parameters
{
get
{
return ((ObservableCollection<ActuatorParameter>)(this["pi_parameters"]));
}
set
{
this["pi_parameters"] = value;
}
}
}
After long research I finally found out that the IntRange class was missing a standard constructor.
[Serializable()]
public class IntRange
{
public int Max { get; set; }
public int Min { get; set; }
public IntRange()
{}
public IntRange(int min, int max)
{
Max = max;
Min = min;
}
public bool isInRange(int value)
{
if (value < Min || value > Max)
return true;
else
return false;
}
}