csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
292 lines
9.1 KiB
292 lines
9.1 KiB
// -----------------------------------------------------------------------
|
|
// <copyright file="PerspexReadOnlyListView.cs" company="Steven Kirk">
|
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|
// </copyright>
|
|
// -----------------------------------------------------------------------
|
|
|
|
namespace Perspex.Collections
|
|
{
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
|
|
public class PerspexReadOnlyListView<T> : IPerspexReadOnlyList<T>, IDisposable
|
|
{
|
|
private IPerspexReadOnlyList<T> source;
|
|
|
|
public PerspexReadOnlyListView()
|
|
: this(null)
|
|
{
|
|
}
|
|
|
|
public PerspexReadOnlyListView(IPerspexReadOnlyList<T> source)
|
|
{
|
|
this.source = source;
|
|
|
|
if (source != null)
|
|
{
|
|
this.source.CollectionChanged += this.SourceCollectionChanged;
|
|
}
|
|
}
|
|
|
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
public int Count
|
|
{
|
|
get { return this.source?.Count ?? 0; }
|
|
}
|
|
|
|
public IPerspexReadOnlyList<T> Source
|
|
{
|
|
get
|
|
{
|
|
return this.source;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (this.source != null)
|
|
{
|
|
this.source.CollectionChanged -= this.SourceCollectionChanged;
|
|
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
var ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Remove,
|
|
this.source,
|
|
0);
|
|
this.CollectionChanged(this, ev);
|
|
}
|
|
}
|
|
|
|
this.source = value;
|
|
|
|
if (this.source != null)
|
|
{
|
|
this.source.CollectionChanged += this.SourceCollectionChanged;
|
|
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
var ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Add,
|
|
this.source.ToList(),
|
|
0);
|
|
this.CollectionChanged(this, ev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public T this[int index]
|
|
{
|
|
get { return this.source[index]; }
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
this.source.CollectionChanged -= this.SourceCollectionChanged;
|
|
}
|
|
|
|
public IEnumerator<T> GetEnumerator()
|
|
{
|
|
return (this.source != null) ?
|
|
this.source.GetEnumerator() :
|
|
Enumerable.Empty<T>().GetEnumerator();
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return this.GetEnumerator();
|
|
}
|
|
|
|
private void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
NotifyCollectionChangedEventArgs ev;
|
|
|
|
switch (e.Action)
|
|
{
|
|
case NotifyCollectionChangedAction.Add:
|
|
ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Add,
|
|
e.NewItems,
|
|
e.NewStartingIndex);
|
|
break;
|
|
case NotifyCollectionChangedAction.Remove:
|
|
ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Remove,
|
|
e.OldItems,
|
|
e.OldStartingIndex);
|
|
break;
|
|
case NotifyCollectionChangedAction.Replace:
|
|
ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Replace,
|
|
e.NewItems,
|
|
e.OldItems,
|
|
e.OldStartingIndex);
|
|
break;
|
|
|
|
default:
|
|
throw new NotSupportedException("Action not yet implemented.");
|
|
}
|
|
|
|
this.CollectionChanged(this, ev);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class PerspexReadOnlyListView<TIn, TOut> : IPerspexReadOnlyList<TOut>, IDisposable
|
|
{
|
|
private IPerspexReadOnlyList<TIn> source;
|
|
|
|
private Func<TIn, TOut> convert;
|
|
|
|
public PerspexReadOnlyListView(Func<TIn, TOut> convert)
|
|
: this(null, convert)
|
|
{
|
|
}
|
|
|
|
public PerspexReadOnlyListView(IPerspexReadOnlyList<TIn> source, Func<TIn, TOut> convert)
|
|
{
|
|
this.source = source;
|
|
this.convert = convert;
|
|
|
|
if (source != null)
|
|
{
|
|
this.source.CollectionChanged += this.SourceCollectionChanged;
|
|
}
|
|
}
|
|
|
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
|
|
public int Count
|
|
{
|
|
get { return this.source?.Count ?? 0; }
|
|
}
|
|
|
|
public IPerspexReadOnlyList<TIn> Source
|
|
{
|
|
get
|
|
{
|
|
return this.source;
|
|
}
|
|
|
|
set
|
|
{
|
|
if (this.source != null)
|
|
{
|
|
this.source.CollectionChanged -= this.SourceCollectionChanged;
|
|
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
var ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Remove,
|
|
this.ConvertList(this.source),
|
|
0);
|
|
this.CollectionChanged(this, ev);
|
|
}
|
|
}
|
|
|
|
this.source = value;
|
|
|
|
if (this.source != null)
|
|
{
|
|
this.source.CollectionChanged += this.SourceCollectionChanged;
|
|
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
var ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Add,
|
|
this.ConvertList(this.source),
|
|
0);
|
|
this.CollectionChanged(this, ev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public TOut this[int index]
|
|
{
|
|
get
|
|
{
|
|
return (this.convert != null) ?
|
|
this.convert(this.source[index]) :
|
|
(TOut)(object)this.source[index];
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (this.source != null)
|
|
{
|
|
this.source.CollectionChanged -= this.SourceCollectionChanged;
|
|
}
|
|
}
|
|
|
|
public IEnumerator<TOut> GetEnumerator()
|
|
{
|
|
if (this.source != null)
|
|
{
|
|
return this.source.Select(this.convert).GetEnumerator();
|
|
}
|
|
else
|
|
{
|
|
return Enumerable.Empty<TOut>().GetEnumerator();
|
|
}
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return this.GetEnumerator();
|
|
}
|
|
|
|
private IList ConvertList(IEnumerable list)
|
|
{
|
|
return list.Cast<TIn>().Select(this.convert).ToList();
|
|
}
|
|
|
|
private void SourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
|
{
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
NotifyCollectionChangedEventArgs ev;
|
|
|
|
switch (e.Action)
|
|
{
|
|
case NotifyCollectionChangedAction.Add:
|
|
ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Add,
|
|
this.ConvertList(e.NewItems),
|
|
e.NewStartingIndex);
|
|
break;
|
|
case NotifyCollectionChangedAction.Remove:
|
|
ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Remove,
|
|
this.ConvertList(e.OldItems),
|
|
e.OldStartingIndex);
|
|
break;
|
|
case NotifyCollectionChangedAction.Replace:
|
|
ev = new NotifyCollectionChangedEventArgs(
|
|
NotifyCollectionChangedAction.Replace,
|
|
this.ConvertList(e.NewItems),
|
|
this.ConvertList(e.OldItems),
|
|
e.OldStartingIndex);
|
|
break;
|
|
|
|
default:
|
|
throw new NotSupportedException("Action not yet implemented.");
|
|
}
|
|
|
|
this.CollectionChanged(this, ev);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|