Browse Source

Added code for listening for indexer updates via INotifyPropertyChanged.

pull/446/head
Jeremy Koritzinsky 11 years ago
parent
commit
5ed27d36d3
  1. 13
      src/Markup/Perspex.Markup/Data/CommonPropertyNames.cs
  2. 49
      src/Markup/Perspex.Markup/Data/IndexerNode.cs
  3. 1
      src/Markup/Perspex.Markup/Perspex.Markup.csproj
  4. 35
      tests/Perspex.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

13
src/Markup/Perspex.Markup/Data/CommonPropertyNames.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Perspex.Markup.Data
{
public static class CommonPropertyNames
{
public const string IndexerName = "Item";
}
}

49
src/Markup/Perspex.Markup/Data/IndexerNode.cs

@ -6,6 +6,7 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
@ -40,6 +41,22 @@ namespace Perspex.Markup.Data
{
incc.CollectionChanged += CollectionChanged;
}
var inpc = target as INotifyPropertyChanged;
if(inpc != null)
{
inpc.PropertyChanged += IndexerPropertyChanged;
}
}
private void IndexerPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var typeInfo = sender.GetType().GetTypeInfo();
if (typeInfo.GetDeclaredProperty(e.PropertyName).GetIndexParameters().Any())
{
CurrentValue = GetValue(sender);
}
}
protected override void Unsubscribe(object target)
@ -108,17 +125,8 @@ namespace Perspex.Markup.Data
}
else
{
PropertyInfo indexerProperty = null;
ParameterInfo[] indexerParameters = null;
foreach (var property in typeInfo.DeclaredProperties)
{
var indexParams = property.GetIndexParameters();
if (indexParams.Length > 0)
{
indexerProperty = property;
indexerParameters = indexParams;
}
}
var indexerProperty = GetIndexer(typeInfo);
var indexerParameters = indexerProperty?.GetIndexParameters();
if (indexerProperty != null && indexerParameters.Length == Arguments.Count)
{
var convertedObjectArray = new object[indexerParameters.Length];
@ -138,6 +146,25 @@ namespace Perspex.Markup.Data
return PerspexProperty.UnsetValue;
}
private static PropertyInfo GetIndexer(TypeInfo typeInfo)
{
PropertyInfo indexer;
// Check for the default indexer name first to make this faster.
// This will only be false when a class in VB has a custom indexer name.
if ((indexer = typeInfo.GetDeclaredProperty(CommonPropertyNames.IndexerName)) != null)
{
return indexer;
}
foreach (var property in typeInfo.DeclaredProperties)
{
if (property.GetIndexParameters().Any())
{
return property;
}
}
return null;
}
private bool InBounds(int[] args, Array array)
{
if (args.Length == array.Rank)

1
src/Markup/Perspex.Markup/Perspex.Markup.csproj

@ -41,6 +41,7 @@
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Data\CommonPropertyNames.cs" />
<Compile Include="Data\ExpressionNodeBuilder.cs" />
<Compile Include="Data\ExpressionParseException.cs" />
<Compile Include="Data\ExpressionSubject.cs" />

35
tests/Perspex.Markup.UnitTests/Data/ExpressionObserverTests_Indexer.cs

@ -146,5 +146,40 @@ namespace Perspex.Markup.UnitTests.Data
Assert.Equal(new[] { "bar", PerspexProperty.UnsetValue }, result);
}
[Fact]
public void Should_Track_NonIntegerIndexer()
{
var data = new { Foo = new NonIntegerIndexer() };
data.Foo["foo"] = "bar";
data.Foo["baz"] = "qux";
var target = new ExpressionObserver(data, "Foo[foo]");
var result = new List<object>();
var sub = target.Subscribe(x => result.Add(x));
data.Foo["foo"] = "bar2";
var expected = new[] { "bar", "bar2" };
Assert.Equal(expected, result);
}
private class NonIntegerIndexer : NotifyingBase
{
private Dictionary<string, string> storage = new Dictionary<string, string>();
public string this[string key]
{
get
{
return storage[key];
}
set
{
storage[key] = value;
RaisePropertyChanged(CommonPropertyNames.IndexerName);
}
}
}
}
}

Loading…
Cancel
Save