Browse Source

support parse cast in binding path expression

pull/5038/head
Andrey Kunchev 6 years ago
parent
commit
5500c2ed8c
  1. 36
      src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs
  2. 19
      src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs

36
src/Markup/Avalonia.Markup/Markup/Parsers/BindingExpressionGrammar.cs

@ -46,6 +46,10 @@ namespace Avalonia.Markup.Parsers
state = ParseIndexer(ref r, nodes); state = ParseIndexer(ref r, nodes);
break; break;
case State.TypeCast:
state = ParseTypeCast(ref r, nodes);
break;
case State.ElementName: case State.ElementName:
state = ParseElementName(ref r, nodes); state = ParseElementName(ref r, nodes);
mode = SourceMode.Control; mode = SourceMode.Control;
@ -124,6 +128,10 @@ namespace Avalonia.Markup.Parsers
{ {
return State.Indexer; return State.Indexer;
} }
else if (ParseOpenBrace(ref r))
{
return State.TypeCast;
}
return State.End; return State.End;
} }
@ -186,6 +194,27 @@ namespace Avalonia.Markup.Parsers
return State.AfterMember; return State.AfterMember;
} }
private static State ParseTypeCast(ref CharacterReader r, List<INode> nodes)
{
var (ns, typeName) = ParseTypeName(ref r);
nodes.Add(new TypeCastNode { Namespace = ns, TypeName = typeName });
if (ParseMemberAccessor(ref r))
{
var identifier = r.ParseIdentifier();
nodes.Add(new PropertyNameNode { PropertyName = identifier.ToString() });
}
if (r.End || !r.TakeIf(')'))
{
throw new ExpressionParseException(r.Position, "Expected ')'.");
}
return State.AfterMember;
}
private static State ParseElementName(ref CharacterReader r, List<INode> nodes) private static State ParseElementName(ref CharacterReader r, List<INode> nodes)
{ {
var name = r.ParseIdentifier(); var name = r.ParseIdentifier();
@ -322,6 +351,7 @@ namespace Avalonia.Markup.Parsers
BeforeMember, BeforeMember,
AttachedProperty, AttachedProperty,
Indexer, Indexer,
TypeCast,
End, End,
} }
@ -383,5 +413,11 @@ namespace Avalonia.Markup.Parsers
public string TypeName { get; set; } public string TypeName { get; set; }
public int Level { get; set; } public int Level { get; set; }
} }
public class TypeCastNode : INode
{
public string Namespace { get; set; }
public string TypeName { get; set; }
}
} }
} }

19
src/Markup/Avalonia.Markup/Markup/Parsers/ExpressionParser.cs

@ -59,6 +59,9 @@ namespace Avalonia.Markup.Parsers
case BindingExpressionGrammar.NameNode elementName: case BindingExpressionGrammar.NameNode elementName:
nextNode = new ElementNameNode(_nameScope, elementName.Name); nextNode = new ElementNameNode(_nameScope, elementName.Name);
break; break;
case BindingExpressionGrammar.TypeCastNode typeCast:
nextNode = ParseTypeCastNode(typeCast);
break;
} }
if (rootNode is null) if (rootNode is null)
{ {
@ -92,6 +95,22 @@ namespace Avalonia.Markup.Parsers
return new FindAncestorNode(ancestorType, ancestorLevel); return new FindAncestorNode(ancestorType, ancestorLevel);
} }
private TypeCastNode ParseTypeCastNode(BindingExpressionGrammar.TypeCastNode node)
{
Type castType = null;
if (!(node.Namespace is null) && !(node.TypeName is null))
{
if (_typeResolver == null)
{
throw new InvalidOperationException("Cannot parse a binding path with a typed Cast without a type resolver. Maybe you can use a LINQ Expression binding path instead?");
}
castType = _typeResolver(node.Namespace, node.TypeName);
}
return new TypeCastNode(castType);
}
private AvaloniaPropertyAccessorNode ParseAttachedProperty(BindingExpressionGrammar.AttachedPropertyNameNode node) private AvaloniaPropertyAccessorNode ParseAttachedProperty(BindingExpressionGrammar.AttachedPropertyNameNode node)
{ {
if (_typeResolver == null) if (_typeResolver == null)

Loading…
Cancel
Save