Extending PX.Objects.CR.CRMSourcesAttribute - acumatica

I am trying to add entries to the CRMSourcesAttribute class for more options in the Opportunities Dropdown Box.
I see PXAttributeExtension but apparently this is not meant for developers as I cannot provide a constructor for the base class PXStringListAttribute where the actual values are set.
There must be a simple way to add entries to that dropdown box!

You don't even need to do any customization or programming to change this list. By adding the screen to Automation Steps screen, you can put the Source field in the Fields tab of the automation definition and override the combo box values. Please note that if you're trying that with Acumatica 5.0, you may need to remove the "Opportunities" list as entry point from the generic inquiries, otherwise it will interfere with your selection when you try to select the Opportunities screen from the Automation Steps.
If you want to do it via programming - you'd need to replace the CRMSourcesAttribute on the field with your own version of this attribute. This attribute is fairly simple and is only derived from PXStringList attribute:
public class CRMSourcesAttribute : PXStringListAttribute
{
public const string _WEB = "W";
public const string _PHONE_INQ = "H";
public const string _REFERRAL = "R";
public const string _PURCHASED_LIST = "L";
public const string _OTHER = "O";
public CRMSourcesAttribute() :
base(new[] { _WEB, _PHONE_INQ, _REFERRAL, _PURCHASED_LIST, _OTHER },
new[] { Messages.Web, Messages.PhoneInq, Messages.Referral, Messages.PurchasedList, Messages.Other })
{
}
}

Related

Check if ListBoxFor selectedValues is null before display in view?

I have a number of ListBoxFor elements on a form in edit mode. If there was data recorded in the field then the previously selected items are displaying correctly when the form opens. If the field is empty though an error is thrown as the items parameter cannot be null. Is there a way to check in the view and if there is data to use the ListBoxFor with the four parameters but if there isn't to only use three parameters, leaving out the selected items?
This is how I'm declaring the ListBoxFor:
#Html.ListBoxFor(model => model.IfQualityPoor, new MultiSelectList(ViewBag.IfPoor, "Value", "Text", ViewBag.IfQualityPoorSelected), new { #class = "chosen", multiple = "multiple" })
I'm using the ViewBag to pass the ICollection which holds the selected items as the controller then joins or splits the strings for binding to the model field. The MultiSelectLists always prove problematic for me.
Your question isn't entirely clear, but you're making it way harder on yourself than it needs to be using ListBoxFor. All you need for either DropDownListFor or ListBoxFor is an IEnumerable<SelectListItem>. Razor will take care of selecting any appropriate values based on the ModelState.
So, assuming ViewBag.IfPoor is IEnumerable<SelectListItem>, all you need in your view is:
#Html.ListBoxFor(m => m.IfQualityPoor, (IEnumerable<SelectListItem>)ViewBag.IfPoor, new { #class = "chosen" })
The correct options will be marked as selected based on the value of IfQualityPoor on your model, as they should be. Also, it's unnecessary to pass multiple = "multiple" in in your htmlAttributes param, as you get that just by using ListBoxFor rather than DropDownListFor.
It's even better if you use a view model and then add your options as a property. Then, you don't have to worry about casting in the view, which is always a good way to introduce runtime exceptions. For example:
public class FooViewModel
{
...
public IEnumerable<SelectListItem> IfQualityPoorOptions { get; set; }
}
Then, you set this in your action, before returning the view (instead of setting ViewBag). Finally, in your view:
#Html.ListBoxFor(m => m.IfQualityPoor, Model.IfQualityPoorOptions, new { #class = "chosen" })
Much simpler, and you'll never have any issues doing it that way.
UPDATE (based on comment)
The best way to handle flattening a list into a string for database storage is to use a special property for that, and then custom getter and setter to map to/from. For example:
public string IfQualityPoor
{
get { return IfQualityPoorList != null ? String.Join(",", IfQualityPoorList) : null; }
set { IfQualityPoorList = !String.IsNullOrWhiteSpace(value) ? value.Split(',').ToList() : null; }
}
[NotMapped]
public List<string> IfQualityPoorList { get; set; }
Then, you post to/interact with IfQualityPoorList, and the correct string will be set in the database automatically when you save.

How to uppercase entire variable in Resharper Template?

I have a situation where I want the variable to be capitalized for documentation eg
(trivalized for example)
///AT+$COMMAND$
void At$COMMAND$()
{
}
So I want the user of the template to type in something like "Blah" and that gets used in the method name, but the documentation part gets changed to "BLAH".
eg
///AT+BLAH
void AtBlah()
{
}
Can I do this? I see in the macros I can capitalize the first letter, but I'd like the whole word capitalized. Is it possible to create custom macros?
They just updated documentation to meet changes in macros in Resharper 8. You can check it at http://confluence.jetbrains.com/display/NETCOM/4.04+Live+Template+Macros+%28R8%29
With the new docs it is quite easy, my implementation goes here:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using JetBrains.DocumentModel;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Macros;
using JetBrains.ReSharper.Feature.Services.LiveTemplates.Hotspots;
namespace ReSharperPlugin
{
[MacroDefinition("LiveTemplatesMacro.CapitalizeVariable", // macro name should be unique among all other macros, it's recommended to prefix it with your plugin name to achieve that
ShortDescription = "Capitalizes variable {0:list}", // description of the macro to be shown in the list of macros
LongDescription = "Capitalize full name of variable" // long description of the macro to be shown in the area below the list
)]
public class CapitalizeVariableMacro : IMacroDefinition
{
public string GetPlaceholder(IDocument document, IEnumerable<IMacroParameterValue> parameters)
{
return "A";
}
public ParameterInfo[] Parameters
{
get { return new[] {new ParameterInfo(ParameterType.VariableReference)}; }
}
}
[MacroImplementation(Definition = typeof(CapitalizeVariableMacro))]
public class CapitalizeVariableMacroImpl : SimpleMacroImplementation
{
private readonly IMacroParameterValueNew _parameter;
public CapitalizeVariableMacroImpl([Optional] MacroParameterValueCollection parameters)
{
_parameter = parameters.OptionalFirstOrDefault();
}
public override string EvaluateQuickResult(IHotspotContext context)
{
return _parameter == null ? null : _parameter.GetValue().ToUpperInvariant();
}
}
}

Changing text field of button in for loop

I'm making a level select screen and I need the text field to display different level numbers for each level. I don't really see what I'm doing wrong here, but I'll go over what I did and post the relevant code.
I have a button class (linked) and inside the symbol I have a dynamic text field. I have two classes of relevance, LevelSelectScreen and LevelSelectButtons (pretty self-explanatory what they are). I thought it would be really easy to change the text if I did it inside the LevelSelectButtons class, by simply doing levelText.text = "Wanted Text", where levelText is the given instance name for my button (just a text field on top of my graphic for the button). Unfortunately, this gives the oh so common and annoying error: TypeError: Error #1009: Cannot access a property or method of a null object reference.
I tried doing virtually the same thing in my LevelSelectScreen class during my loop, but I got the same error. Help on how to get this levelText to work is greatly appreciated! Here is the relevant code.
LevelSelectScreen
public class LevelSelectButtons extends SimpleButton {
public var levelNumber:int;
public var levelSelectScreen:LevelSelectScreen;
public function LevelSelectButtons(i) {
x = 200;
y = 100 + 50*i;
addEventListener(MouseEvent.CLICK,LevelSelectClicked,false,0,true)
levelNumber = i;
levelText.text = "Level" + i;
}
}
LevelSelectScreen
public class LevelSelectScreen extends MovieClip {
public var levelSelectButtons:LevelSelectButtons;
public var mainMenuButton:MainMenuButton;
public function LevelSelectScreen() {
for (var i:int = 1; i<=2; i++)
{
levelSelectButtons = new LevelSelectButtons(i);
addChild(levelSelectButtons);
}
}
}
You can't have a dynamic text field in a SimpleButton.
Annoying, I know.
Simple fix would be to have LevelSelectButton wrap a SimpleButton instead of extend it. Then your text field would be inside LevelSelectButton on top of a text-less SimpleButton. (Be sure to set mouseEnabled to false on the text field so it doesn't interfere with mouse events on the SimpleButton.
A more complex option would be to write your own custom button class.
It's not actually that difficult, but might be overkill for what you're trying to do here.
its because you haven't declared levelText variable and you are trying to access it, therefor Cannot access a property or method of a null object reference.

Can I use mutiple RuleSet withe in a same Validator Attribute in Microsoft Enterprise Library Validation Framework

Helllo..... I am quite new in Microsoft Enterprise Library Validation Framework. My question is that I want same validation condition in two different RuleSet.
Is it possible to put two rule set with in the same Validator like below
/// <summary>
///
/// </summary>
[StringLengthValidator(1,25,Ruleset="DetailRuleSet",Ruleset="MainRuleSet",Tag="First Name")]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
or I have mentioned it by writing the same in two time with different ruleset name like below
/// <summary>
///
/// </summary>
[StringLengthValidator(1,25,Ruleset="DetailRuleSet",Tag="First Name")]
[StringLengthValidator(1, 25, Ruleset = "MainRuleSet", Tag = "First Name")]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
Any help would be appreciated!!
First a disclaimer: I haven't worked so much on the Enterprise Library Application Validation Block, however, having been a programmer for over a decade and a half, and having used Validation models from ASP.NET to MVC Data Annotations, I can tell you that the API for validation in Enterprise Library is pretty similar. It took me about 20 minutes to download the Enterprise Library source code and look up the answer to this question. So, here's my answer.
Yes, you can apply more than one validation attribute to a given model property, each validation attribute specifying a different rule set.
However, in such a case, you will have to explicitly invoke the validator on the model type for that particular rule set.
If you do not do that, the Enterprise Library will execute the validator for the default rule-set.
In the context of your example, you can say:
StringLengthValidator(1,25,Ruleset="DetailRuleSet",Tag="First Name")]
[StringLengthValidator(1, 25, Ruleset = "MainRuleSet", Tag = "First Name")]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
However, in this case, you have to specifically invoke one of the rule-sets for validation, like so:
var yourModelObjectValidator =
yourValidatorFactory.CreateValidator<YourModelClass>("yourRuleSetName");
var yourModelObject =
new YourModelClass { Foo = "foo", Bar = "bar", Gar = 2 };
var results =
yourModelObjectValidator.Validate(yourModelObject);
if (!results.IsValid)
{
foreach(var result in results)
{
/* run the state machine, do whatever, print */
}
}
If you do not specify the rule set name like we did above, the Enterprise Library will execute your validations in the context of a default rule set which has no name, and hence none of the two rules you specified above using the validation attributes will get executed.
UPDATE
Based on your comment, I see what your real question is.
Your question then really is: Can I specify more than a single rule-set in a single validation attribute declaration?
The answer is as simple as the question: No. Because the property RuleSet is declared simply as string and not as IEnumerable<string> in the BaseValidationAttribute class, the mother of all ValidatorAttribute classes in the EntLib source code.

Adding custom control with a collection property to a SharePoint Page Layout

I have created a custom control with a collection property per the example on How do you build an ASP.NET custom control with a collection property?
When the control is added to a common ASP.Net aspx page it works as expected. However, when added to a Page Layout in Sharepoint the following error is thrown:
Unable to cast object of type 'System.Web.UI.CollectionBuilder' to type 'System.Collections.Generic.List`1[mytypes.mytype]'.
The code is pretty much identical to the code provided by the example shown in the link above. I do not think the fault lies in the control as it works fine in a plain web project.
I dont think you can use generic lists in sharepoint. Use an ArrayList or customised List collection instead (use asp:ListItem as an exampe, it has its own collection type)
[ParseChildren(true, "Names")]
public class MyControl : Control {
private List<PersonName> names;
public MyControl() {
names = new List<PersonName>();
}
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public List<PersonName> Names {
get { return this.names; }
}
}
public class PersonName {
public string Name { get; set; }
}
UPDATE
Ahh i see the problem now, it is not to do with the generic list, it is because of the way you are doing the initialization.
Create a private variable to hold the list private List<PersonName> names;
Ensure that the property does not have a setter

Resources