How and where is x:Key implemented in MAUI? - xamarin

x:Key behaves like an attached property where it is available in the children of ResourceDictionary. However, I cannot find the implementation of x:Key in ResourceDictionary (the repo).
Question: How and where is x:Key implemented in MAUI?

x:Key, along with other attributes that are part of the xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" namespace are special XmlNames, that are built into the XAML parser; they are not implemented as attached properties. Basically, they are almost equivalent to keywords in C#.
You can view the static variable declarations for them here, inside the XmlName struct: https://github.com/dotnet/maui/blob/main/src/Controls/src/Xaml/XmlName.cs
For instance, the static XmlName field 'xKey' (x:Key) is referenced here in the XamlParser class: https://github.com/dotnet/maui/blob/main/src/Controls/src/Xaml/XamlParser.cs#L261
The other special XAML attributes that are implemented in the same way are:
x:Arguments, x:DataType, x:FactoryMethod, x:Name, x:TypeArguments.
x:Class and x:FieldModifier are also part of the x: namespace, but they're kind of a special case.
Edit: Should mention that if you want to create your own set of extensions that behave similarly, you can create what's called a Markup Extension. Though you can't directly add to the x: namespace. x:Static for instance is implemented as a markup extension: https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Xaml/MarkupExtensions/StaticExtension.cs

Related

Add textfield for Classes in cq dialog

If we want to add an Id to an AEM Core component such as image, there is this field:
.content.xml
<id
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldDescription="HTML ID attribute to apply to the component."
fieldLabel="ID"
name="./id"/>
which gives this textfield in the dialog.
But what if we want to create the same textfield, but for CLASSES instead? The core components only seems to use the "./id" name, and nothing for classes.
As you can see I am an absolute beginner, so any pointer or help is much appreciated.
--- Edit (June 17, 2022):
Following Vlad's answer, I needed to narrow down where I am having issue:
I don't know how to "add a textfield for classes". For example, the id field has name="./id" in the xml, which can be accessed as "${image.id}" in the html. But the same doesn't exist for Classes.
How would the Textfield look like if I am adding it for Classes? Like this one obviously wouldn't work as "./class" is not connected to anywhere.
<class
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldDescription="HTML CLASS attribute to apply to the component."
fieldLabel="CLASS"
name="./class"/>
I guess that the name="./id" of the Textfield is tied to some Java logic so we can retrieve it via "${image.id}". I have looked at image's java code, but don't see how they tied together.
I would need to understand the Java code in order to override it. Or am I missing anything and there is an easier way? Again, absolute beginner here.
You can override the dialog and add a textfield for classes, then overlay the HTL script and inject the classes in the markup. However, I recommend you look first into the OOTB Style System. It allows you to define classes in the component’s policy and then use them in the editor (they will be added on the component wrapper element).

How to do get value from custom geojson prop without properties for paint expression in Mapbox

I want to change features style according to in features style property. But style is not in properties. A sample feature is like that,
{
type:"feature",
style:{polygon:{"line-color":"#FF0000"}},
properties:{...},
geometry:{...}
}
So, according to documents 'get' expression does not work. Because, it looks for property section Document Mapbox Expressions.
I was wondering, are there any method to get information from style section in the features?
No, in a style, there is no way to access any part of an object other than in the properties section. (The one exception to this is the id property).
You will need to process your data differently.

Override EditorTemplate based on BeginForm

I am using EditorTemplates to style all my input fields. Works like a charm, however now I want two themes of EditorTemplates, one for normal forms, and then one for my wizard forms.
I am already using an overloaded Html.BeginWizardForm() around those Html.EditorFor - but how do I make the MVC logic react on being inside Html.BeginWizardForm() ?
EditorTemplates are designed to be somewhat global. You can override them, though, just like any other view, because they are just views. For example, assuming you have something like Views\Shared\EditorTemplates\String.cshtml, you can then create a another view at Views\Foo\EditorTemplates\String.cshtml, and for any action called from FooController, the latter editor template will be used instead of the one from Shared. You might be able to make this work in your scenario if the wizard form is used in a specific controller or area context.
Short of that, though, there's no way to have this occur automatically. Some manual options still exist, though.
You can decorate the properties of the view model used within the context of the wizard with UIHint attributes. For example, assuming the same shared editor template above, you could do something like:
[UIHint("WizardString")]
public string Foo { get; set; }
That would cause it to look for Views\Shared\EditorTemplates\WizardString.cshtml instead.
You can pass the editor template to use in the call to EditorFor:
#Html.EditorFor(m => m.Foo, "WizardString")
All that said, the biggest problem here is that you seem to be violating a pretty core principal of good web design. HTML is about structure, not presentation. CSS is for presentation. As a result, if you want something to look different in a certain context, the correct approach is to apply different CSS. If things are designed well, your HTML shouldn't really have to change.
It seems is as stated by Chris Pratt not possible to have multiple EditorTemplates.
I however found a workaround by extending the MvcForm and created a WizardForm which adds a value to the ViewContext (in my case "wizardContext" => true) and on disposing setting wizardContext => false.
This allows me in the EditorTemplates to add a check for if I am inside or outside the wizardContext, which will propagate through the nested EditorFor, and in this way allow me to have different themes, without having to be specific in EditorFor.

Find component using CSS selector in TestUtils

I'm writing some simple tests for my React components using TestUtils and I'm finding that both the TestUtils.FindRenderedDOMComponentWithClass and TestUtils.FindRenderedDOMComponentWithTag methods are pretty limiting. I'd like to find a component using the typical CSS selector (i.e. tag.class [attr]) but it doesn't seem like this is an option.
Is there a simple way to find an element with a specific attribute? If not are there any useful tools for finding components apart from TestUtils?
I find it useful to simply use the browser's Element.querySelector()/querySelectorAll() method on DOM elements.
You can just call for example like this:
var domElement = FindRenderedDOMComponentWithClass('myClass');
var firstTextInput = domElement.querySelector('input[type="text"]');
React.TestUtils does not offer component searches with CSS selectors so I went with a lightweight extension of the base TestUtils class called react-testutils-addition. It offeres a find() method which parses the CSS selector style input and uses TestUtils.findAllInRenderedTree to find the component.

Is it possible to define a big part of xaml as a tag and use this tag in different places?

I have a big part of xaml code (ListBox & ListBoxItems) and I need to use this ListBox in different places. I'd like to define this ListBox once to use it like: <my:SimpleListBox /> instead of copy/paste. Is it possible?
Yes. Just define it as a UserControl. See a complete example here in the documentation.
http://msdn.microsoft.com/en-us/library/system.windows.controls.usercontrol%28v=vs.95%29.aspx
There are a couple of options:
A UserControl - The regular way of encapsulating a part of the UI with a single project.
A Templated (or Custom) Control - The regular way of encapulating a control and making it 'Templateable' and reusable across applications
A string of XAML - A very uncommon way of storing a part of the UI. Use the XAML Serializer to load it.
Consider 1 first then 2 and use 3 only when messing around or when you know what you are doing.

Resources