Browse Source

Allow indexer bindings to be at the start of a binding path.

pull/1595/head
Jeremy Koritzinsky 9 years ago
parent
commit
8d8480c086
  1. 4
      src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs
  2. 42
      src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs
  3. 12
      tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

4
src/Markup/Avalonia.Markup/Data/Parsers/ArgumentListParser.cs

@ -51,10 +51,10 @@ namespace Avalonia.Markup.Data.Parsers
}
}
throw new ExpressionParseException(r.Position, "Expected ']'.");
throw new ExpressionParseException(r.Position, $"Expected '{close}'.");
}
return null;
throw new ExpressionParseException(r.Position, $"Expected '{open}'.");
}
}
}

42
src/Markup/Avalonia.Markup/Data/Parsers/ExpressionParser.cs

@ -40,6 +40,10 @@ namespace Avalonia.Markup.Data.Parsers
case State.AttachedProperty:
state = ParseAttachedProperty(r, nodes);
break;
case State.Indexer:
state = ParseIndexer(r, nodes);
break;
}
}
@ -67,6 +71,10 @@ namespace Avalonia.Markup.Data.Parsers
{
return State.AttachedProperty;
}
else if (PeekOpenBracket(r))
{
return State.Indexer;
}
else
{
var identifier = IdentifierParser.Parse(r);
@ -92,20 +100,9 @@ namespace Avalonia.Markup.Data.Parsers
nodes.Add(new StreamNode());
return State.AfterMember;
}
else
else if (PeekOpenBracket(r))
{
var args = ArgumentListParser.Parse(r, '[', ']');
if (args != null)
{
if (args.Count == 0)
{
throw new ExpressionParseException(r.Position, "Indexer may not be empty.");
}
nodes.Add(new IndexerNode(args));
return State.AfterMember;
}
return State.Indexer;
}
return State.End;
@ -151,6 +148,19 @@ namespace Avalonia.Markup.Data.Parsers
return State.AfterMember;
}
private State ParseIndexer(Reader r, List<ExpressionNode> nodes)
{
var args = ArgumentListParser.Parse(r, '[', ']');
if (args.Count == 0)
{
throw new ExpressionParseException(r.Position, "Indexer may not be empty.");
}
nodes.Add(new IndexerNode(args));
return State.AfterMember;
}
private static bool ParseNot(Reader r)
{
return !r.End && r.TakeIf('!');
@ -166,6 +176,11 @@ namespace Avalonia.Markup.Data.Parsers
return !r.End && r.TakeIf('(');
}
private static bool PeekOpenBracket(Reader r)
{
return !r.End && r.Peek == '[';
}
private static bool ParseStreamOperator(Reader r)
{
return !r.End && r.TakeIf('^');
@ -177,6 +192,7 @@ namespace Avalonia.Markup.Data.Parsers
AfterMember,
BeforeMember,
AttachedProperty,
Indexer,
End,
}
}

12
tests/Avalonia.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

@ -338,6 +338,18 @@ namespace Avalonia.Markup.UnitTests.Data
GC.KeepAlive(data);
}
[Fact]
public async Task Indexer_Only_Binding_Works()
{
var data = new[] { 1, 2, 3 };
var target = new ExpressionObserver(data, "[1]");
var value = await target.Take(1);
Assert.Equal(data[1], value);
}
private class NonIntegerIndexer : NotifyingBase
{
private readonly Dictionary<string, string> _storage = new Dictionary<string, string>();

Loading…
Cancel
Save