Can you help me on what to select? I’ve gone through the list of available conditions and none look relevant. Or do I skip the condition and go straight from Start to Execute custom code?
private void QuoteHed_BeforeFieldChange(object sender, DataColumnChangeEventArgs args)
{
switch (args.Column.ColumnName)
{
case "ShortChar02": /* QuoteStatus */
if ( (args.Row["ShortChar02"].ToString().Contains("Won") || args.Row["ShortChar02"].ToString().Contains("Lost")) &&
(args.ProposedValue.ToString().Contains("Progress") || args.ProposedValue.ToString().Contains("Finished")) )
{
if (args.Row["Date03"].ToString() != string.Empty)
{
DialogResult dialogResult = EpiMessageBox.Show("Continue? Your Date Won/Lost will be cleared.", "Warning", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes) {
/* Reset Status Date */
args.Row["Date03"] = DBNull.Value;
}
else {
throw new UIException();
}
}
}
}
}
Basically args.ProposedValue is what the new change will be and if you don’t like it then throw new UIException(); Which will prevent it from going to the AfterFieldChange and it will also set the User’s Keyboard focus, back on the field.
Few more Examples:
/* Status Date */
case "Date03":
if (!string.IsNullOrEmpty(args.ProposedValue.ToString()))
{
// Get Proposed Date Change Value
DateTime dt = Convert.ToDateTime(args.ProposedValue);
// If its past the Date Quoted dont allow it
if (!string.IsNullOrEmpty(args.Row["DateQuoted"].ToString()))
{
if (dt < Convert.ToDateTime(args.Row["DateQuoted"]))
{
MessageBox.Show("You are not allowed to set a date that is less than the Date Quoted", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
throw new UIException();
}
}
}
break;
case "DateQuoted":
case "FollowUpDate":
case "DueDate":
// Check if Selected Date is Good
if (!this.CheckProposedDate(args))
{
throw new UIException();
}
break;
Just for the sake, let’s show the “AfterFieldChange” what I usually do in there:
private void QuoteHed_AfterFieldChange(object sender, DataColumnChangeEventArgs args)
{
// ** Argument Properties and Uses **
// args.Row["FieldName"]
// args.Column, args.ProposedValue, args.Row
// Add Event Handler Code
switch (args.Column.ColumnName)
{
/* ParentQuoteNum is Manually Changed */
case "ParentQuoteNum":
if (Convert.ToInt32(args.ProposedValue.ToString()) == 0 && args.Row["ShortChar01"].ToString() == "Revision")
{
args.Row["ShortChar01"] = "Quote";
}
else if (Convert.ToInt32(args.ProposedValue.ToString()) > 0 && args.Row["ShortChar01"].ToString() == "Quote")
{
args.Row["ShortChar01"] = "Revision";
}
break;
/* Due Date is Changed */
case "DueDate":
DialogResult dialogResult = EpiMessageBox.Show("Changing the Due Date should only be done if authorized by the Customer. Would you like to Log a Call to Contact the Customer?", "Due Date Warning", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
// Launch Log a Call
Erp.UI.App.CRMCallEntry.CRMCallArgs crmObject = new CRMCallArgs(RelatedToFiles.QuoteHed, args.Row["QuoteNum"].ToString(), "", "", "", "", "", false);
ProcessCaller.LaunchForm(this.oTrans, "Erp.UI.CRMCallEntry", crmObject, false);
}
break;
}
}
This is not trivial for someone not somewhat familiar with C#. and the framework While @hkeric.wci shows you how to navigate the features of the validations, You’ll still have to:
Get the appropriate adapter
GetByID using the passed the CustID
If no results are returned, fail the validation
What table are you updating? The data directive works on a specific table.
The data directive BPM’s will only fire when you make a change to the tables. (like a save event) if you want the validation to happen when you exit the field before you save the record, you will need a customization. Like the thread posted, or like @hkeric.wci’s code that is posted.
Like @Chris_Conn said, not trivial. But I figured it out, so it’s not that hard.
Isnt the CustID already validated? Is the issue you want to stop it from prompting for a new one? If so, just do a BeforeAdapterMethod against GetNew on the CustomerAdapter and stop it.
Wouldn’t a search adapter on Customer be best? (I’m sure I used the wrong terminology there)
It not only ensures that a valid customer number is used, but actually allows you to find the customer you’re looking for.
I should have explained this in full first but didn’t want to post an essay!
I think I actually want to make sure that the entry in UD04 Key1 is a valid Customer.CustID
My Task:
On the customer Entry Program, Ship To Tab:
Make it possible for users to add :
unique machine ID (there can be multiple of these per ship To)
Date installed for each machine
Grade of Anit virus conver puchased for each machine
active / deactivated dates for antivirus cover per machine
I have selected UD04 (we already use 1,2,&3)
UD 04 Key 1 will be the CustomerCustID
UD04 Key 2 will be the ShipTo.ShipToNum
UD04.Character01 will be the MachineID
Before I get to making it work on Customer Entry, I set up UD04 in our menu.
I wanted to be able to add the records there to build up the UD04 Table (in test environment).
And so then I have a place to enter multiple records without opening each customer form up.
At present, Key 1 of UD04 is bound to Customer.CustID, but I could enter anything.
(I have managed to add UD04 to the menu context file xml, and it is available to pull in to a foreign key view).
I would make two buttons Cust ID and Ship To and then use search functions to find each and return to read only text boxes. Validate - check, easy to search - check.
I followed the whole workshop on adding Custom Shipping Size container to Customer shipment entry and the combo never displayed any data (I had added the ud table and populated it wih container options).