projects/wms-framework/src/lib/baseframework/collectionViews.ts
Defines a collection of elements to be displayed in a view
Properties |
SortDescriptions |
SortDescriptions:
|
Type : SortDescriptionCollection
|
Gets the instance of SortDescriptionCollection object that contains all sort criterias |
import { Dependency } from '../basecomponentmodel/Dependency';
import { DependencyObject } from '../basecomponentmodel/DependencyObject';
import { DependencyProperty } from '../basecomponentmodel/DependencyProperty';
import { DependencyPropertyChangedEventArgs } from '../basecomponentmodel/DependencyPropertyChangedEventArgs';
import { INotifyPropertyChanged } from '../basecomponentmodel/INotifyPropertyChanged';
import { IItemsSource } from '../models';
import { SubscriptionEvent } from '../utils/SubscriptionEvent';
import {
CollectionChangeAction,
CollectionChangeInfo,
INotifyCollectionChanged,
SimpleList,
SortDescriptionCollection,
} from './collections';
import { SortDescription } from './SortDescription';
/**
*
* Defines a collection of elements to be displayed in a view
* @export
* @interface ICollectionView
* @extends {Iterable<unknown>}
* @extends {INotifyCollectionChanged}
* @wInterface System.ComponentModel.ICollectionView
*/
export interface ICollectionView
extends Iterable<unknown>,
INotifyCollectionChanged {
/**
* Gets the instance of {@link SortDescriptionCollection} object that contains all
* sort criterias
*
* @type {SortDescriptionCollection}
* @memberof ICollectionView
*/
SortDescriptions: SortDescriptionCollection;
}
/**
* Concrete implementation of {@link ICollectionView } object that just delegates all element operations
* on a given {@link Iterable } object.
*/
export class CollectionView implements ICollectionView, IItemsSource {
private sortDescriptions: SortDescriptionCollection =
new SortDescriptionCollection();
private innerHandler: (e: any, args: CollectionChangeInfo) => void;
private sortHandler: (e: any, args: CollectionChangeInfo) => void;
private sortedList: SimpleList<any>;
// inherited
get SortDescriptions(): SortDescriptionCollection {
return this.sortDescriptions;
}
/**
* Creates an instance of CollectionView.
* @param {Iterable<unknown>} elements
* @memberof CollectionView
*/
constructor(private elements: Iterable<unknown>) {
let notifiable: INotifyCollectionChanged =
elements as any as INotifyCollectionChanged;
if (notifiable?.CollectionChanged) {
this.sortedList = new SimpleList((elements as any).internalArray);
this.innerHandler = notifiable.CollectionChanged.addHandler(
(sender, args) => this.handleInnerChanges(sender, args)
);
} else {
this.sortedList = new SimpleList(elements);
}
this.sortHandler = this.sortDescriptions.CollectionChanged.addHandler(
(sender, args) => this.handleSortDescriptionChanges()
);
}
// inherited
get internalArray() {
return this.sortedList?.internalArray;
}
/**
* Releases all resources associated to this Collection view object
*
* @memberof CollectionView
*/
release() {
if (this.innerHandler) {
let notifiable: INotifyCollectionChanged = this
.elements as any as INotifyCollectionChanged;
if (notifiable) {
notifiable.CollectionChanged.removeHandler(this.innerHandler);
}
}
this.sortDescriptions.CollectionChanged.removeHandler(this.sortHandler);
}
/**
* Handles changes in the Sorted Description object by resorting all elements in the list
* with the new sorting descriptors
* @param sender
* @param args
*/
private handleSortDescriptionChanges(): void {
this.sort();
let args: CollectionChangeInfo = new CollectionChangeInfo(
CollectionChangeAction.Reset
);
this.CollectionChanged.fire([this, args]);
}
/**
* Sorts the underlying list with current SortDescription object
*
* @private
* @memberof CollectionView
*/
private sort() {
this.sortedList.sort((x: any, y: any) =>
SortDescription.sortFunction(this.sortDescriptions, x, y)
);
}
/**
* Handles the underlying INotifyCollectionChanged changes by recreating the list and sorting it
* with the new changes
*
* @private
* @param {*} sender
* @param {CollectionChangeInfo} args
* @memberof CollectionView
*/
private handleInnerChanges(sender: any, args: CollectionChangeInfo) {
this.sortedList = new SimpleList((this.elements as any).internalArray);
this.sort();
this.CollectionChanged.fire([sender, args]);
}
// inherited
*[Symbol.iterator](): Iterator<unknown, any, undefined> {
for (const e of this.sortedList) {
yield e;
}
}
// inherited
CollectionChanged: SubscriptionEvent<
(e: any, args: CollectionChangeInfo) => void
> = new SubscriptionEvent();
}
/**
* Provides a binding mechanism that is strongly coupled with the component bound to
*
* @export
* @class CollectionViewSource
* @extends {DependencyObject}
* @wType System.Windows.Data.CollectionViewSource
*/
export class CollectionViewSource
extends DependencyObject
implements INotifyPropertyChanged
{
PropertyChanged: SubscriptionEvent<
(o: any, args: { PropertyName: string }) => void
> = new SubscriptionEvent<(o: any, args: { PropertyName: string }) => void>();
/**
* SourceProperty dependency property
*
* @static
* @type {DependencyProperty}
* @memberof CollectionViewSource
*/
static SourceProperty: DependencyProperty = new DependencyProperty(
'Source',
null,
CollectionViewSource.sourceChanged
);
/**
* Provides a source to be strongly bound to a control, acting as a proxy between the component
* and the given source.
* ViewProperty dependency property
*
* @static
* @type {DependencyProperty}
* @memberof CollectionViewSource
*/
static ViewProperty: DependencyProperty = new DependencyProperty(
'View',
null,
CollectionViewSource.viewChanged
);
/**
* Gets/sets the data source for this { CollectionViewSource } object.
*
* @type {*}
* @memberof ListBox
*/
@Dependency(CollectionViewSource.SourceProperty)
public Source: any;
/**
* Gets/sets the { IViewCollection } object used to render this data.
*
* @type {*}
* @memberof ListBox
*/
@Dependency(CollectionViewSource.ViewProperty)
public View: ICollectionView;
/**
* A change handler responsible for handlingchanges of source property
* @param sender the sender object
* @param args a {@link DependencyPropertyChangedEventArgs } object that has the changed values
*/
public static sourceChanged(
sender: DependencyObject,
args: DependencyPropertyChangedEventArgs
): void {
let collection: CollectionViewSource = sender as CollectionViewSource;
if (collection) {
let newSource: Iterable<unknown> = args.NewValue as Iterable<unknown>;
collection.View = newSource ? new CollectionView(newSource) : null;
}
}
/**
* A change handler responsible for handling changes of view property
* @param sender the sender object
* @param args a {@link DependencyPropertyChangedEventArgs } object that has the changed values
*/
public static viewChanged(
sender: DependencyObject,
args: DependencyPropertyChangedEventArgs
): void {
let collection: CollectionViewSource = sender as CollectionViewSource;
if (collection) {
let oldView: CollectionView = args.OldValue as CollectionView;
oldView?.release();
collection.PropertyChanged.fire([collection, { PropertyName: 'View' }]);
}
}
}