graph extension is marked as [PXOverride], but the original method with such name has not been found in PXGraph - acumatica

I'm needing to adjust some of the field attributes for the Location.VCashAccountID field on the Vendors screen - AP303000. When I put the code below into a customization DLL, it compiles fine and there are not apparent issues on the screen. However, when I try to publish the customization project with the DLL included, I get an error.
Code:
public class VendorMaintDefLocationExtExt : PXGraphExtension<VendorMaint.DefLocationExt,
VendorMaint>
{
public void _(Events.CacheAttached<PX.Objects.CR.Standalone.Location.vCashAccountID> e) { }
}
Error:
"Method Boolean DoValidateAddresses(PX.Objects.CR.Extensions.ValidateAddressesDelegate) in graph extension is marked as [PXOverride], but the original method with such name has not been found in PXGraph"
What am I missing?
TIA!

The following implementation will override the vCashAccount attribute on AP303000
public class AAVendorMaintDefLocationExtExtension : PXGraphExtension<DefLocationExt, DefContactAddressExt, VendorMaint>
{
[PXMergeAttributes(Method = MergeMethod.Merge)]
[PXUIField(DisplayName = "I am override")]
public void _(Events.CacheAttached<PX.Objects.CR.Standalone.Location.vCashAccountID> e) { }
}
You will also require the following references
using PX.Data;
using PX.Objects.AP;
using static PX.Objects.AP.VendorMaint;
The result can be seen in the snip below
The main difficulty in this task was the multitude of graph extensions utilized by the page. Though it's a beneficial design to encapsulate functionality it can be finnicky to determine which order they should be declared in a new extension.

You're graph extension extends VendorMaint.DefLocationExt which contains DoValidateAddresses. Try just extending VendorMaint.

Related

Override BQL used for PXProjection on SOShipmentPlan

I have a need to override the Select statement being used for the SOShipmentPlan PXProjection/DAC, namely, removing the
And <INPlanType.isFixed, Equal<boolFalse>
condition.
I can override all of the CreateShipment() logic and bring in any other necessary routines into an SOShipmentEntry_Extension class, to the point where I finally can use my own version of a SOShipmentPlan class, but that all seems needlessly complex when all I want to do is override the select for the PXProjection attribute. Overriding CreateShipment() and supporting routines also seems like a quick way to get in trouble come time for upgrades.
So, is there an easy way to override the PXProjection's BQL, or am I stuck overriding all kinds of code?
UPDATE 1
Based on a link provided below (stackoverflow.com/a/41540659/7376238), I feel like I'm close. Here's the block of code I end up with:
namespace PX.Objects.SO
{
public class SOShipmentEntry_Extension : PXGraphExtension<SOShipmentEntry>
{
#region Event Handlers
#endregion
[Serializable]
[PXProjection(typeof(Select2<SOOrder,
InnerJoin<SOOrderType, On<SOOrder.FK.OrderType>,
InnerJoin<INItemPlan, On<INItemPlan.refNoteID, Equal<SOOrder.noteID>>,
InnerJoin<INPlanType, On<INItemPlan.FK.PlanType>>>>,
Where<INItemPlan.hold, Equal<boolFalse>,
And<INItemPlan.planQty, Greater<decimal0>,
And<INPlanType.isDemand, Equal<boolTrue>,
And<INPlanType.isForDate, Equal<boolTrue>,
And<Where<INItemPlan.fixedSource, IsNull,
Or<INItemPlan.fixedSource, NotEqual<INReplenishmentSource.transfer>>>>>>>>>))]
[PXSubstitute()]
public partial class SOShipmentPlanCst : SOShipmentPlan
{
int x = 0;
}
}
But it doesn't seem to work. Not sure of where I'm supposed to put the code. I've tried putting the class definition inside and outside of public class SOShipmentEntry_Extension : PXGraphExtension<SOShipmentEntry> class (currently inside the extension class as shown). No luck either way.
THIS ANSWER DIDN'T WORK
Fair warning... I have not done this to a PXProjection before, so you'll have to see if this works. The nature of extensions tends to allow overriding views by simply redefining them. I have not done this myself with a projection, but I suspect it will be similar. Give it a try and see if you get the desired results. All I can say about testing it is that "it compiled" when I added to my project and removed the INItemPLanType.isFixed condition.
public class SOShipmentEntry_Extension : PXGraphExtension<SOShipmentEntry>
{
[PXProjection(typeof(Select2<SOOrder,
InnerJoin<SOOrderType, On<SOOrder.FK.OrderType>,
InnerJoin<INItemPlan, On<INItemPlan.refNoteID, Equal<SOOrder.noteID>>,
InnerJoin<INPlanType, On<INItemPlan.FK.PlanType>>>>,
Where<INItemPlan.hold, Equal<boolFalse>,
And<INItemPlan.planQty, Greater<decimal0>,
And<INPlanType.isDemand, Equal<boolTrue>,
And<INPlanType.isForDate, Equal<boolTrue>,
And<Where<INItemPlan.fixedSource, IsNull, Or<INItemPlan.fixedSource, NotEqual<INReplenishmentSource.transfer>>>>>>>>>))]
public partial class SOShipmentPlan : IBqlTable { }
}

Xamarin Forms - CustomObject, XAML Initialization, Setter not called, DependencyProperty, I'm lost?

I have a problem and I searched a solution about it. Lucky, I red lot of post about it but I'm lost with the explaination I found. The initale problem is coming from a personal project about the polyline of the Xamarin.Forms.Map where the initialization is realized by a binding from the XAML part..
Let me be clear by an example :
I have an object CustomMap.cs which inherit from Xamarin.Forms.Map (This file is in the PCL part -> CustomControl/CustomMap.cs)
public class CustomMap : Map, INotifyPropertyChanged
{
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(List<string>), typeof(CustomMap), null);
public List<string> PolylineAddressPoints
{
get { return (List<string>)GetValue(PolylineAddressPointsProperty); }
set
{
SetValue(PolylineAddressPointsProperty, value);
this.GeneratePolylineCoordinatesInner();
}
}
// ...
}
So the Xaml part of the page, where the control is called, looks like that:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:MapPolylineProject.CustomControl;assembly=MapPolylineProject"
x:Class="MapPolylineProject.Page.MainPage">
<ContentPage.Content>
<control:CustomMap x:Name="MapTest" PolylineAddressPoints="{Binding AddressPointList}"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
</ContentPage.Content>
</ContentPage>
The Csharp part:
public partial class MainPage : ContentPage
{
public List<string> AddressPointList { get; set; }
public MainPage()
{
base.BindingContext = this;
AddressPointList = new List<string>()
{
"72230 Ruaudin, France",
"72100 Le Mans, France",
"77500 Chelles, France"
};
InitializeComponent();
//MapTest.PolylineAddressPoints = AddressPointList;
}
}
So, everything is fine if I edit the PolylineAddressPoints from the object instance (if the commented part isnt' commented..), but if I init the value from the XAML (from the InitializeComponent();), it doesn't work, the SetValue, in the Set {}, isn't called..
I then searched on the web about it and get something about the Dependency Properties? or something like that. So I tried some solutions but, from WPF, so some methods, such as DependencyProperty.Register();. So yeah, I can't find the way to solve my problem..
I also though about something, if DependencyProperty.Register(); would exists in Xamarin.Forms, then it means I would have to do it for each values? Because, if every value has to be set by a XAML binding logic, it would not work, I would have to register every value, doesn't it?
I'm sorry if I'm not clear, but I'm so lost about this problem.. Please, do not hesitate to ask for more details, thank in advance !
I finaly got a solution just over here => Ignore the Binding initialization
Copy paste from Stackoverflow. This following answer was given by Stephane Delcroix, thank to him !
There are multiple questions in this:
Why is the property setter never called when using Xaml ?
Am I properly defining my BindableProperty ?
Why is my binding failing ?
Let me answer them in a different order.
Am I properly defining my BindableProperty ?
The BindableProperty declaration is right, but could be improved by using an IList<string>:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null);
but the property accessor is wrong, and should only contains this:
public IList<string> PolylineAddressPoints
{
get { return (IList<string>)GetValue(PolylineAddressPointsProperty); }
set { SetValue(PolylineAddressPointsProperty, value); }
}
I'll tell you why while answering the next question. But you want to invoke a method when the property has changed. In order to do that, you have to reference a propertyChanged delegate to CreateBindableProperty, like this:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null,
propertyChanged: OnPolyLineAddressPointsPropertyChanged);
And you have to declare that method too:
static void OnPolyLineAddressPointsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
((CustomMap)bindable).OnPolyLineAddressPointsPropertyChanged((IList<string>)oldValue, (IList<string>)newValue);
}
void OnPolyLineAddressPointsPropertyChanged(IList<string> oldValue, IList<string> newValue)
{
GeneratePolylineCoordinatesInner();
}
Why is the property setter never called when using Xaml ?
The property, and the property accessors, are only meant to be invoked when accessing the property by code. C# code.
When setting a property with a BindablePrperty backing store from Xaml, the property accessors are bypassed and SetValue() is used directly.
When defining a Binding, both from code or from Xaml, property accessors are again bypassed and SetValue() is used when the property needs to be modified. And when SetValue() is invoked, the propertyChanged delegate is executed after the property has changed (to be complete here, propertyChanging is invoked before the property change).
You might wonder why bother defining the property if the bindable property is only used by xaml, or used in the context of Binding. Well, I said the property accessors weren't invoked, but they are used in the context of Xaml and XamlC:
a [TypeConverter] attribute can be defined on the property, and will be used
with XamlC on, the property signature can be used to infer, at compile time, the Type of the BindableProperty.
So it's a good habit to always declare property accessors for public BindableProperties. ALWAYS.
Why is my binding failing ?
As you're using CustomMap as bot View and ViewModel (I won't tell the Mvvm Police), doing this in your constructor should be enough:
BindingContext = this; //no need to prefix it with base.
As you're doing it already, your Binding should work once you've modified the BindableProperty declaration in the way I explained earlier.

running a T4 on adding a class

Using t4, I want when the developer adds a class which ends to Report keyword (e.g. CompanyReport), put some code in that class.
Imagine I create a class named CompanyReport, I want the class to be like :
public class CompanyReport : IReportItem
{
private Company _company;
public CompanyReport(Company company)
{
_company = company;
}
public ReportBookmark BookMark
{
get { return ReportBookmark.Company; }
}
public void Report(ISetBookmark wordReport)
{
}
}
Maybe you should consider using a customized ItemTemplate for Visual Studio or just a snippet. Both are quite easy to build and redistribute. I'am also not sure if it is possible to invoke some T4-Template on creating (and really ONLY on creating) a class.

Create SharePoint (2010) ToolPart usable for more than one WebPart

I am using the basic instructions (here) for creating a property driven by a custom ToolPart.
All is good, except for the part where, in order to access the webpart property within the ApplyChanges method I must cast the "this.ParentToolPane.SelectedWebPart" back to a concrete "SimpleWebPart" class.
public override void ApplyChanges()
{
SimpleWebPart wp1 = (SimpleWebPart)this.ParentToolPane.SelectedWebPart;
// Send the custom text to the Web Part.
wp1.Text = Page.Request.Form[inputname];
}
Doing this means that I must pair each toolpart with a specific webpart. Is there a better way?
I cannot create an interface as there is no way of specifying a property in one.
I ineptly tried an passing an event/eventhandler during toolpart creation, but that did not update the webpart property when called.
I could create a base class for all the webparts that have a public "Text" property, but that is fugly.
I could also get desperate and crack open the this.ParentToolPane.SelectedWebPart reference with Reflection and call any properties named "Text" that way.
Either way, I am staring down the barrel of a fair bit of faffing around only to find out each option is a dead end.
Has anyone done this and can recommend the correct method for creating a reusable toolpart?
I have used an interface instead of a specific instance of a webpart.
private class IMyProperty
{
void SetMyProperty(string value);
}
public override void ApplyChanges()
{
IMyProperty wp1 = (IMyProperty)this.ParentToolPane.SelectedWebPart;
// Send the custom text to the Web Part.
wp1.SetMyProperty(Page.Request.Form[inputname]);
}
But this does not give a compile time warning that the toolpart requires the parent webpart to implement the IMyProperty interface.
The simple solution to that is to add a property of the IMyProperty interface in the toolpart constructor and call this reference instead of the this.ParentToolPane.SelectedWebPart property.
public ToolPart1(IContentUrl webPart)
{
// Set default properties
this.Init += new EventHandler(ToolPart1_Init);
parentWebPart = webPart;
}
public override void ApplyChanges()
{
// Send the custom text to the Web Part.
parentWebPart.SetMyProperty(Page.Request.Form[inputname]);
}
public override ToolPart[] GetToolParts()
{
// This is the custom ToolPart.
toolparts[2] = new ToolPart1(this);
return toolparts;
}
This works fine, but I cannot get over the feeling that there is something nasty in the underlying SharePoint code that may trip me up later.

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