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);
break;
case State.TypeCast:
state = ParseTypeCast(ref r, nodes);
break;
case State.ElementName:
state = ParseElementName(ref r, nodes);
mode = SourceMode.Control;
@ -124,6 +128,10 @@ namespace Avalonia.Markup.Parsers
{
return State.Indexer;
}
else if (ParseOpenBrace(ref r))
{
return State.TypeCast;
}
return State.End;
}
@ -186,6 +194,27 @@ namespace Avalonia.Markup.Parsers
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)
{
var name = r.ParseIdentifier();
@ -322,6 +351,7 @@ namespace Avalonia.Markup.Parsers
BeforeMember,
AttachedProperty,
Indexer,
TypeCast,
End,
}
@ -383,5 +413,11 @@ namespace Avalonia.Markup.Parsers
public string TypeName { 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:
nextNode = new ElementNameNode(_nameScope, elementName.Name);
break;
case BindingExpressionGrammar.TypeCastNode typeCast:
nextNode = ParseTypeCastNode(typeCast);
break;
}
if (rootNode is null)
{
@ -92,6 +95,22 @@ namespace Avalonia.Markup.Parsers
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)
{
if (_typeResolver == null)

Loading…
Cancel
Save