AllowMultiple does not work with Property Attributes? - attributes

I'm tying to collect all Custom Attributes placed over a Property. There are more than one Attributes of the same type assigned to the Property, but when collecting them , the resulting collection only contains the first Attribute of the specific type:
The Attribute class
[AttributeUsage(System.AttributeTargets.Property,
AllowMultiple = true)]
public class ConditionAttribute : Attribute{...}
Usage:
[ConditionAttribute("Test1")]
[ConditionAttribute("Test2")]
[ConditionAttribute("Test3")]
public Color BackColor{get; set;}
Now when looping through all Props of the object 'value' whose class contains the Prop "BackColor":
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value))
{
foreach (Attribute attribute in property.Attributes)
{ ... }
....
}
the collection property.Attributes only contains ONE Attribute of type "ConditionAttribute" : The one with "Test1". The others are ignored;-(
So does AllowMultiple not work for Property Attributes ?
Thanks in advance
henrik

According to a post on MSDN, this is by design as part of the PropertyDescriptor class.
However, you can actually solve the problem by overriding TypeId in your custom attribute (Thanks to Ivan from Mindscape for pointing this out):
public override object TypeId
{
get
{
return this;
}
}

Yes, it does work. Not sure why it does not work via PropertyDescriptors.
You can always do: Attribute.GetCustomAttributes(methodInfo, typeof(ConditionAttribute))

Another way to tweak this,
[ConditionAttribute("Test1,Test2,Test3")]
public Color BackColor{get; set;}
and in your validation code,
Dim lstProperties() As String = _ChkColors.Split(",")
For each strProp as string in lstPropertyes
' your validation
' return
Next

Related

PXFormula not updating

I've created a new custom bound field UsrMatchCode for the BAccount DAC. My goal is to create a field which I can query from a web service call to identify "potential" duplicate customer records. My plan is to concatenate the following into a single 9-character calculated field:
First 5 Characters of Address.PostalCode
First 2 Characters of Address.AddressLine1
First 2 Characters of Contact.FullName
But before I can get this far, I'm stuck getting the value of the PXFormula to display when updating/saving existing records. Strangely, it does output a value for new records. See screenshot.
I've reduced the PXFormula to using constants only to rule out other fields causing the problem.
public class BAccountExt : PXCacheExtension<PX.Objects.CR.BAccount>
{
private class index1 : Constant<int>
{
public index1() : base(0) { }
}
private class length5 : Constant<int>
{
public length5() : base(5) { }
}
private class testString : Constant<string>
{
public testString() : base("123456789") { }
}
#region UsrMatchCode
public abstract class usrMatchCode : IBqlField { }
[PXDBString(9)]
[PXUIField(DisplayName = "Match Code", Enabled = false)]
[PXFormula(typeof(Substring<testString, index1, length5>))]
public virtual string UsrMatchCode { get; set; }
#endregion
}
I feel like I'm missing something obvious, but I can't work it out.
I avoid using PXFormula and PXDBxxx types at the same time.
The PXDBxxx attribute tells the framework you want to persist the field value to DB and reload it's value from DB while PXFormula tells the framework the string value needs to be computed from the formula. The two approach appear incompatible because it's not clear cut whether the value will be coming from DB or from formula after the record has been persisted to DB. Other attributes like PXDefault are more suited for PXDBxxx types because it will only run at initialisation.
I would recommend either to use PXFormula with the unbound PXString type or to use PXDefault instead of PXFormula for initialisation of PXDBString.

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.

Using "Content" view as EditorFor template in an "Embedded Resource" view

I have an "Embedded Resource" view. In this view I am using the following model
public class TestModel
{
public TestModel()
{
CustomModel1 = new CustomModel1 ();
CustomModel2 = new CustomModel2();
}
public CustomModel1 CustomModel1 { get; set; }
public CustomModel2 CustomModel2{ get; set; }
}
In this view I have a form and inside it I am using #Html.EditorFor instead of #Html.Partial, because when I use #Html.Partial the CustomModel1 passed to the action (when the form is submitted) is empty.
#Html.EditorFor(m => m.CustomModel1, Constants.CustomEmbeddedView1)
However when I use #Html.EditorFor and pass as a template a "Content" view
#Html.EditorFor(m => m.CustomModel1, "~/Views/Common/_CustomPartialView.cshtml")
I get the following error:
The model item passed into the dictionary is null, but this dictionary requires a non-null model item of type 'System.Int32'.
If I set the "Content" view to be an "Embedded Resource" everything works fine.
Is there any way to resolve this problem? Perhaps there is another solution to the model binding problem instead of using #Html.EditorFor.
I found a solution to my problem. I still do not know why the error is thrown, but at least I fixed the model binding.
The problem with the model binding, is that when you call #Html.Partial
#Html.Partial("~/Views/Common/_CustomPartialView.cshtml", Model.CustomModel1)
The elements that are dispayed (I use #Html.EditorFor(m => m.Name) for example in the partial view) have an id="Name". So the model binding tries to find a "Name" property inside the TestModel, but the name property is inside the CustomModel1 property. This is why the model binding does not work, and the Name property is an empty string when the form is submitted.
The fix is to set the HtmlFieldPrefix.
var dataDictCustomModel1 = new ViewDataDictionary { TemplateInfo = { HtmlFieldPrefix = "CustomModel1" } };
#Html.Partial("~/Views/Common/_CustomPartialView.cshtml", Model.CustomModel1, dataDictCustomModel1 )
This way the id of the Name property becomes id="CustomModel1_Name", thus allowing the model binder to properly set the value of the Name property.
There may be a better solution for this, but so far this is the best, that I have come up with.

Uses and differences in properties?

whats difference between Auto-Implemented Properties and manual properties in c#?
for Example:
Manual Properties:
private int uno;
public int Uno
{
get { return uno; }
set { uno = value; }
}
Auto Implemented Prop:
public string UserLeaveCount { get; set; }
i found the difference and uses here : Auto Implemented Prop
But Here is my Specific doubt thats "there is no instance variable in auto implemented properties and how is it stored,returned values?"
It's just syntactic sugar -- the compiler inserts the backing field for you. The effect is the same, except that, of course, there's no way for you to access the backing field from your code.
From the page you linked to:
When you declare a property as shown in the following example, the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.

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