Skip to content

Commit

Permalink
Implement IListSource on LocalView and EntityQueryable to further dir…
Browse files Browse the repository at this point in the history
…ect data binding

Issues #8898 #8899
  • Loading branch information
ajcvickers committed Jun 28, 2017
1 parent a02d1b3 commit f1a9378
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
24 changes: 23 additions & 1 deletion src/EFCore/ChangeTracking/LocalView.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
Expand Down Expand Up @@ -46,7 +47,7 @@ namespace Microsoft.EntityFrameworkCore.ChangeTracking
/// </para>
/// </summary>
/// <typeparam name="TEntity">The type of the entity in the local view.</typeparam>
public class LocalView<TEntity> : ICollection<TEntity>, INotifyCollectionChanged, INotifyPropertyChanged, INotifyPropertyChanging
public class LocalView<TEntity> : ICollection<TEntity>, INotifyCollectionChanged, INotifyPropertyChanged, INotifyPropertyChanging, IListSource
where TEntity : class
{
private ObservableBackedBindingList<TEntity> _bindingList;
Expand Down Expand Up @@ -443,5 +444,26 @@ private void OnCollectionChanged(NotifyCollectionChangedAction action, object it
/// <returns> The binding list. </returns>
public virtual BindingList<TEntity> ToBindingList()
=> _bindingList ?? (_bindingList = new ObservableBackedBindingList<TEntity>(ToObservableCollection()));

/// <summary>
/// <para>
/// This method is called by data binding frameworks when attempting to data bind
/// directly to a <see cref="LocalView{TEntity}" />.
/// </para>
/// <para>
/// This implementation always throws an exception as <see cref="LocalView{TEntity}" />
/// does not maintain an ordered list with indexes. Instead call <see cref="ToObservableCollection" />
/// for WPF binding, or <see cref="ToBindingList" /> for WinForms.
/// </para>
/// </summary>
/// <exception cref="NotSupportedException"> Always thrown. </exception>
/// <returns> Never returns, always throws an exception. </returns>
IList IListSource.GetList() => throw new NotSupportedException(CoreStrings.DataBindingWithIListSource);

/// <summary>
/// Gets a value indicating whether the collection is a collection of System.Collections.IList objects.
/// Always returns false.
/// </summary>
bool IListSource.ContainsListCollection => false;
}
}
29 changes: 28 additions & 1 deletion src/EFCore/Query/Internal/EntityQueryable`.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Utilities;
using Microsoft.EntityFrameworkCore.Internal;
using Remotion.Linq;

namespace Microsoft.EntityFrameworkCore.Query.Internal
Expand All @@ -13,7 +17,7 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
public class EntityQueryable<TResult> : QueryableBase<TResult>, IAsyncEnumerable<TResult>, IDetachableContext
public class EntityQueryable<TResult> : QueryableBase<TResult>, IAsyncEnumerable<TResult>, IDetachableContext, IListSource
{
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
Expand All @@ -35,10 +39,33 @@ public EntityQueryable([NotNull] IAsyncQueryProvider provider, [NotNull] Express
{
}

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
IAsyncEnumerator<TResult> IAsyncEnumerable<TResult>.GetEnumerator()
=> ((IAsyncQueryProvider)Provider).ExecuteAsync<TResult>(Expression).GetEnumerator();

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
IDetachableContext IDetachableContext.DetachContext()
=> new EntityQueryable<TResult>(NullAsyncQueryProvider.Instance);

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
IList IListSource.GetList()
{
throw new NotSupportedException(CoreStrings.DataBindingWithIListSource);
}

/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
bool IListSource.ContainsListCollection => false;
}
}
20 changes: 20 additions & 0 deletions test/EFCore.Tests/DbSetTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,26 @@ public void Throws_when_using_with_IListSource()
}
}

[Fact]
public void Throws_when_using_query_with_IListSource()
{
using (var context = new EarlyLearningCenter())
{
Assert.Equal(CoreStrings.DataBindingWithIListSource,
Assert.Throws<NotSupportedException>(() => ((IListSource)context.Gus.Distinct()).GetList()).Message);
}
}

[Fact]
public void Throws_when_using_Local_with_IListSource()
{
using (var context = new EarlyLearningCenter())
{
Assert.Equal(CoreStrings.DataBindingWithIListSource,
Assert.Throws<NotSupportedException>(() => ((IListSource)context.Gus.Local).GetList()).Message);
}
}

private class Category
{
public int Id { get; set; }
Expand Down

0 comments on commit f1a9378

Please sign in to comment.