Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
{
if (parent.XmlType.IsOfAnyType(nameof(Trigger), nameof(DataTrigger), nameof(MultiTrigger), nameof(Style)))
{
typeName = GetTargetTypeName(parent);
typeName = GetTargetTypeFromElement(parent, node.NamespaceResolver, (IXmlLineInfo)node);
}
else if (parent.XmlType.IsOfAnyType(nameof(VisualState)))
{
Expand All @@ -47,7 +47,7 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
}
else if (node.Parent is ElementNode { XmlType: XmlType xt1 } && xt1.IsOfAnyType(nameof(Trigger)))
{
typeName = GetTargetTypeName(node.Parent);
typeName = GetTargetTypeFromElement(node.Parent as ElementNode, node.NamespaceResolver, (IXmlLineInfo)node);
}
propertyName = parts[0];
}
Expand All @@ -71,38 +71,44 @@ public FieldReference GetBindablePropertyFieldReference(string value, ILContext
if (bpRef == null)
throw new BuildException(PropertyResolution, node, null, propertyName, typeRef.Name);
return bpRef;

static XmlType GetTargetTypeName(INode node)
{
var targetType = ((node as ElementNode).Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
return TypeArgumentsParser.ParseSingle(targetType, node.NamespaceResolver, (IXmlLineInfo)node);
}
}

static XmlType FindTypeNameForVisualState(ElementNode parent, IXmlLineInfo lineInfo, ILContext context)
{
//1. parent is VisualState, don't check that
// 1. parent is VisualState, don't check that

//2. check that the VS is in a VSG
// if (!(parent.Parent is IElementNode target) || target.XmlType.NamespaceUri != XamlParser.MauiUri || target.XmlType.Name != nameof(VisualStateGroup))
// 2. check that the VS is in a VSG
if (parent.Parent is not ElementNode target || !target.XmlType.IsOfAnyType(nameof(VisualStateGroup)))
throw new XamlParseException($"Expected {nameof(VisualStateGroup)} but found {parent.Parent}", lineInfo);

//3. if the VSG is in a VSGL, skip that as it could be implicit
if ( target.Parent is ListNode
// 3. if the VSG is in a VSGL, skip that as it could be implicit
if (target.Parent is ListNode
|| target.Parent is ElementNode { XmlType: XmlType xt } && xt.IsOfAnyType(nameof(VisualStateGroupList)))
target = target.Parent.Parent as ElementNode;
else
target = target.Parent as ElementNode;

//4. target is now a Setter in a Style, or a VE
// 4. target is now a Setter in a Style, or a VE
if (target.XmlType.IsOfAnyType(nameof(Setter)))
{
var targetType = ((target?.Parent as ElementNode)?.Properties[new XmlName("", "TargetType")] as ValueNode)?.Value as string;
return TypeArgumentsParser.ParseSingle(targetType, parent.NamespaceResolver, lineInfo);
}
else
return target.XmlType;
return GetTargetTypeFromElement(target?.Parent as ElementNode, parent.NamespaceResolver, lineInfo);

return target.XmlType;
}

/// <summary>
/// Extracts the TargetType attribute from an element node and parses it as an XmlType.
/// Returns null if the element is null, has no TargetType, or TargetType is empty.
/// </summary>
static XmlType GetTargetTypeFromElement(ElementNode element, IXmlNamespaceResolver namespaceResolver, IXmlLineInfo lineInfo)
{
if (element?.Properties.TryGetValue(new XmlName("", "TargetType"), out var targetTypeNode) != true)
return null;

var targetType = (targetTypeNode as ValueNode)?.Value as string;
if (string.IsNullOrEmpty(targetType))
return null;

return TypeArgumentsParser.ParseSingle(targetType, namespaceResolver, lineInfo);
}

public static FieldReference GetBindablePropertyFieldReference(XamlCache cache, TypeReference typeRef, string propertyName, ModuleDefinition module)
Expand Down
4 changes: 4 additions & 0 deletions src/Controls/src/Build.Tasks/CreateObjectVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class CreateObjectVisitor(ILContext context) : IXamlNodeVisitor
public bool StopOnDataTemplate => true;
public bool StopOnResourceDictionary => false;
public bool VisitNodeOnDataTemplate => false;
public bool StopOnStyle => false;
public bool VisitNodeOnStyle => true;
public bool SkipChildren(INode node, INode parentNode) => false;

public bool IsResourceDictionary(ElementNode node)
Expand All @@ -29,6 +31,8 @@ public bool IsResourceDictionary(ElementNode node)
|| parentVar.VariableType.Resolve().BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary";
}

public bool IsStyle(ElementNode node) => false;

public void Visit(ValueNode node, INode parentNode)
{
Context.Values[node] = node.Value;
Expand Down
4 changes: 4 additions & 0 deletions src/Controls/src/Build.Tasks/ExpandMarkupsVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class ExpandMarkupsVisitor(ILContext context) : IXamlNodeVisitor
public bool StopOnDataTemplate => false;
public bool StopOnResourceDictionary => false;
public bool VisitNodeOnDataTemplate => true;
public bool StopOnStyle => false;
public bool VisitNodeOnStyle => true;
public bool SkipChildren(INode node, INode parentNode) => false;

public bool IsResourceDictionary(ElementNode node)
Expand All @@ -31,6 +33,8 @@ public bool IsResourceDictionary(ElementNode node)
|| parentVar.VariableType.Resolve().BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary";
}

public bool IsStyle(ElementNode node) => false;

public void Visit(ValueNode node, INode parentNode)
{
}
Expand Down
4 changes: 4 additions & 0 deletions src/Controls/src/Build.Tasks/SetFieldVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class SetFieldVisitor(ILContext context) : IXamlNodeVisitor
public bool StopOnDataTemplate => true;
public bool StopOnResourceDictionary => false;
public bool VisitNodeOnDataTemplate => false;
public bool StopOnStyle => false;
public bool VisitNodeOnStyle => true;
public bool SkipChildren(INode node, INode parentNode) => false;

public bool IsResourceDictionary(ElementNode node)
Expand All @@ -21,6 +23,8 @@ public bool IsResourceDictionary(ElementNode node)
|| parentVar.VariableType.Resolve().BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary";
}

public bool IsStyle(ElementNode node) => false;

public void Visit(ValueNode node, INode parentNode)
{
if (!IsXNameProperty(node, parentNode))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class SetNamescopesAndRegisterNamesVisitor(ILContext context) : IXamlNodeVisitor
public bool StopOnDataTemplate => true;
public bool StopOnResourceDictionary => false;
public bool VisitNodeOnDataTemplate => false;
public bool StopOnStyle => false;
public bool VisitNodeOnStyle => true;
public bool SkipChildren(INode node, INode parentNode) => false;

public bool IsResourceDictionary(ElementNode node)
Expand All @@ -23,6 +25,8 @@ public bool IsResourceDictionary(ElementNode node)
|| parentVar.VariableType.Resolve().BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary";
}

public bool IsStyle(ElementNode node) => false;

public void Visit(ValueNode node, INode parentNode)
{
Context.Scopes[node] = Context.Scopes[parentNode];
Expand Down
4 changes: 4 additions & 0 deletions src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class SetPropertiesVisitor(ILContext context, bool stopOnResourceDictionary = fa
public TreeVisitingMode VisitingMode => TreeVisitingMode.BottomUp;
public bool StopOnDataTemplate => true;
public bool VisitNodeOnDataTemplate => true;
public bool StopOnStyle => false;
public bool VisitNodeOnStyle => true;
public bool SkipChildren(INode node, INode parentNode) => false;

public bool IsResourceDictionary(ElementNode node)
Expand All @@ -41,6 +43,8 @@ public bool IsResourceDictionary(ElementNode node)
|| parentVar.VariableType.Resolve().BaseType?.FullName == "Microsoft.Maui.Controls.ResourceDictionary";
}

public bool IsStyle(ElementNode node) => false;

ModuleDefinition Module { get; } = context.Body.Method.Module;

// Track properties that have been set to detect duplicates
Expand Down
4 changes: 4 additions & 0 deletions src/Controls/src/Build.Tasks/SetResourcesVisitor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ class SetResourcesVisitor(ILContext context) : IXamlNodeVisitor
public bool StopOnDataTemplate => true;
public bool StopOnResourceDictionary => false;
public bool VisitNodeOnDataTemplate => false;
public bool StopOnStyle => false;
public bool VisitNodeOnStyle => true;

public bool IsStyle(ElementNode node) => false;

public void Visit(ValueNode node, INode parentNode)
{
Expand Down
6 changes: 4 additions & 2 deletions src/Controls/src/Core/IStyle.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#nullable disable
using System;

namespace Microsoft.Maui.Controls
{
interface IStyle
{
Type TargetType { get; }
/// <summary>
/// Gets the target type for this style. May return null for lazy styles if the type was trimmed.
/// </summary>
Type? TargetType { get; }

void Apply(BindableObject bindable, SetterSpecificity specificity);
void UnApply(BindableObject bindable);
Expand Down
16 changes: 10 additions & 6 deletions src/Controls/src/Core/MergedStyle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ sealed class MergedStyle : IStyle

IList<string> _styleClass;

readonly Type _targetType;

public MergedStyle(Type targetType, BindableObject target)
{
Target = target;
TargetType = targetType;
_targetType = targetType;
// RegisterImplicitStyles handles the initial apply via OnImplicitStyleChanged -> SetStyle.
// An explicit Apply(Target) call here would double-attach event handlers when
// Application.Current.Resources already contains the implicit style (#24152).
Expand All @@ -47,8 +49,10 @@ public IStyle Style
{
if (_style == value)
return;
if (value != null && !value.TargetType.IsAssignableFrom(TargetType))
MauiLogger<Style>.Log(LogLevel.Warning, $"Style TargetType {value.TargetType.FullName} is not compatible with element target type {TargetType}");
if (value?.TargetType is Type styleTargetType && !styleTargetType.IsAssignableFrom(_targetType))
{
MauiLogger<Style>.Log(LogLevel.Warning, $"Style TargetType {styleTargetType.FullName} is not compatible with element target type {_targetType}");
}
SetStyle(ImplicitStyle, ClassStyles, value);
}
}
Expand Down Expand Up @@ -116,7 +120,7 @@ void Apply(BindableObject bindable)
Style?.Apply(bindable, new SetterSpecificity(SetterSpecificity.StyleLocal, 0, 0, 0));
}

public Type TargetType { get; }
public Type TargetType => _targetType;

public void UnApply(BindableObject bindable)
{
Expand All @@ -129,7 +133,7 @@ public void UnApply(BindableObject bindable)

void OnClassStyleChanged()
{
ClassStyles = _classStyleProperties.Select(p => (Target.GetValue(p) as IList<Style>)?.FirstOrDefault(s => s.CanBeAppliedTo(TargetType))).ToList();
ClassStyles = _classStyleProperties.Select(p => (Target.GetValue(p) as IList<Style>)?.FirstOrDefault(s => s.CanBeAppliedTo(_targetType))).ToList();
}

void OnImplicitStyleChanged()
Expand All @@ -155,7 +159,7 @@ void OnImplicitStyleChanged()

void RegisterImplicitStyles()
{
Type type = TargetType;
Type type = _targetType;
while (true)
{
BindableProperty implicitStyleProperty = BindableProperty.Create(nameof(ImplicitStyle), typeof(Style), typeof(NavigableElement), default(Style),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~override Microsoft.Maui.Controls.Handlers.Items.MauiRecyclerView<TItemsView, TAdapter, TItemsViewSource>.OnInterceptTouchEvent(Android.Views.MotionEvent e) -> bool
~override Microsoft.Maui.Controls.Handlers.Items.MauiRecyclerView<TItemsView, TAdapter, TItemsViewSource>.OnTouchEvent(Android.Views.MotionEvent e) -> bool
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~const Microsoft.Maui.Controls.AppThemeBinding.AppThemeResource = "__MAUI_ApplicationTheme__" -> string
~override Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.ViewWillTransitionToSize(CoreGraphics.CGSize toSize, UIKit.IUIViewControllerTransitionCoordinator coordinator) -> void
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~const Microsoft.Maui.Controls.AppThemeBinding.AppThemeResource = "__MAUI_ApplicationTheme__" -> string
~override Microsoft.Maui.Controls.Platform.Compatibility.ShellFlyoutRenderer.ViewWillTransitionToSize(CoreGraphics.CGSize toSize, UIKit.IUIViewControllerTransitionCoordinator coordinator) -> void
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~Microsoft.Maui.Controls.ResourceDictionary.AddFactory(string key, System.Func<object> factory, bool shared = true) -> void
~const Microsoft.Maui.Controls.AppThemeBinding.AppThemeResource = "__MAUI_ApplicationTheme__" -> string
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~Microsoft.Maui.Controls.ResourceDictionary.AddFactory(string key, System.Func<object> factory, bool shared = true) -> void
~const Microsoft.Maui.Controls.AppThemeBinding.AppThemeResource = "__MAUI_ApplicationTheme__" -> string
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
2 changes: 2 additions & 0 deletions src/Controls/src/Core/PublicAPI/net/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~Microsoft.Maui.Controls.ResourceDictionary.AddFactory(string key, System.Func<object> factory, bool shared = true) -> void
~const Microsoft.Maui.Controls.AppThemeBinding.AppThemeResource = "__MAUI_ApplicationTheme__" -> string
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ virtual Microsoft.Maui.Controls.LongPressingEventArgs.GetPosition(Microsoft.Maui
~Microsoft.Maui.Controls.ResourceDictionary.AddFactory(System.Type targetType, System.Func<Microsoft.Maui.Controls.Style> factory, bool shared = true) -> void
~Microsoft.Maui.Controls.ResourceDictionary.AddFactory(string key, System.Func<object> factory, bool shared = true) -> void
~static Microsoft.Maui.Controls.VisualStateManager.GetVisualStateGroups(Microsoft.Maui.Controls.VisualElement visualElement) -> Microsoft.Maui.Controls.VisualStateGroupList
~Microsoft.Maui.Controls.Style.LazyInitialization.set -> void
~Microsoft.Maui.Controls.Style.Style(string assemblyQualifiedTargetTypeName) -> void
2 changes: 1 addition & 1 deletion src/Controls/src/Core/ResourceDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ event EventHandler<ResourcesChangedEventArgs> IResourceDictionary.ValuesChanged
public void Add(Style style)
{
if (string.IsNullOrEmpty(style.Class))
Add(style.TargetType.FullName, style);
Add(style.TargetTypeFullName, style);
else
{
IList<Style> classes;
Expand Down
Loading
Loading