Reputation: 330
I have model like below
public class Person
{
[Display(Name = "Name of the Person", Prompt = "Enter your Name")]
public string Name { get; set; }
}
.net MAUI content Page as below
<StackLayout>
<Label Text="{Binding DisplayNameAnnotation}"/>
<Entry Text="{Binding Person.Name}" Placeholder="{Binding DisplayPromptAnnotation}"/>
</StackLayout>
The expected outcome is as shown in the image
The purpose is to have a common model for asp.net and .net maui with annotations and efcore decorations.Syncfusion's dataform does this by default. We cannot use syncfusion.
DisplayNameAnnotation and DisplayPromptAnnotation are written for illustration only. Binding the Name to the entry control is straight forward. I wanted to bind the corresponding annotations to placeholder or text of another label. This is straight forward in asp.net application with labelfor kind of tags. But, in .net MAUI, I could not able to figure out a way to do it. Can any one point to me in right direction.
Upvotes: 0
Views: 339
Reputation: 8220
Update
Seems that you want to reuse the Converter and you don't want to assign the Type to be only Person. Though we Reflection to GetCustomAttributes
, I think we have to know the Type.
One way is to utilize the ConverterParameter
. If you want the Converter
to be generic, I think you at least have to pass 3 parameters,
1.Namespace name.
2.Class name,
3.Property name,
Then the question comes to how to pass multiple parameters to a Converter. There are several ways to achieve that. One of the easiest ways I think is to use ConverterParameter=Namespace|ClassName|PropertyName
and retrieve the corresponding value in Converter
using String.Split("|") method.
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
string[] parameters = ((string)parameter).Split("|");
string myNamespace = parameters[0];
string myClassName = parameters[1];
string myProperty = parameters[2];
Type myType = Type.GetType(string.Format("{0}.{1}", myNamespace, myClassName), true);
MemberInfo prop = myType.GetProperty(myProperty);
DisplayAttribute[] attr = prop.GetCustomAttributes(typeof(DisplayAttribute)) as DisplayAttribute[];
if(attr.Length == 0)
{
return value;
}
else
{
return attr[0].GetName();
}
//throw new NotImplementedException();
}
...
There is no direct way to bind Display attributes in MAUI. But you could use ValueConverter to achieve that.
Suppose there is a Name Porperty with DisplayAttribute in ViewModel,
public class MainPageViewModel
{
public Person Person { get; set; } = new Person();
}
public class Person
{
[Display(Name = "Name of the Person", Prompt = "Enter your Name")]
public string Name { get; set; } = "Default Name";
}
What we want to do is to use in XAML like the following,
<ContentPage.Resources>
<local:GetDisplayName x:Key="getDisplayName" />
</ContentPage.Resources>
...
<StackLayout>
<Label Text="{Binding Person.Name,Converter={StaticResource getDisplayName},ConverterParameter=Name}"/>
<Entry Text="{Binding Person.Name}" />
</StackLayout>
Then this is our ValueConverter,
public class GetDisplayName : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
MemberInfo prop = typeof(Person).GetProperty((string)parameter);
DisplayAttribute[] attr = prop.GetCustomAttributes(typeof(DisplayAttribute)) as DisplayAttribute[];
if(attr.Length == 0)
{
return value;
}
else
{
return attr[0].GetName();
}
//throw new NotImplementedException();
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
return Binding.DoNothing;
}
}
Upvotes: 1