Skip to content

Instantly share code, notes, and snippets.

@clairernovotny
Last active February 17, 2017 10:32
Show Gist options
  • Save clairernovotny/5008551 to your computer and use it in GitHub Desktop.
Save clairernovotny/5008551 to your computer and use it in GitHub Desktop.
Pattern to use collection views in a portable class library with WPF and WinRT XAML. The issue is that while WPF and WinRT both have the CollectionView concepts, they're in different namespaces, so you can't use them in a PCL ViewModel. This wrapper allows you to wrap a collection view source and manipulate it in a PCL for navigation, etc. This …
// These classes would go in your PCL
public interface IWrappedCollectionView
{
bool MoveCurrentTo(object item);
bool MoveCurrentToPosition(int position);
bool IsCurrentAfterLast { get; }
bool MoveCurrentToFirst();
bool IsCurrentBeforeFirst { get; }
bool MoveCurrentToLast();
bool MoveCurrentToNext();
bool MoveCurrentToPrevious();
}
public interface IWrappedCollectionViewSource
{
object UnderlyingSource { get; }
IWrappedCollectionView View { get; }
object Source { get; set; }
}
public static class CollectionViewSourceFactory
{
public static IWrappedCollectionViewSource Create()
{
return ServiceLocator.Current.GetInstance<IWrappedCollectionViewSource>();
}
}
<ListBox ItemsSource="{Binding ItemsView.UnderlyingSource.View}"
SelectedItem="{Binding CurrentItem, Mode=TwoWay}">
// Example view model
public class ViewModel
{
public IWrappedCollectionViewSource ItemsView { get; private set; }
private ObservableCollection<object> _data = new ObservableCollection<object>();
public ViewModel()
{
ItemsView = CollectionViewSourceFactory.Create();
ItemsView.Source = _data;
}
public void AddItem()
{
_data.Add(...);
}
public void SelectNextItem()
{
if (ItemsView.View == null)
return;
ItemsView.View.MoveCurrentToNext();
if (ItemsView.View.IsCurrentAfterLast)
ItemsView.View.MoveCurrentToFirst();
}
public object CurrentItem { get; set;} // would want to implement INPC here
}
// This goes into your platform-specific code (entrypoint, library, etc)
internal class WrappedCollectionViewSource : IWrappedCollectionViewSource
{
private readonly CollectionViewSource _source = new CollectionViewSource();
private readonly WrappedView _view;
public WrappedCollectionViewSource()
{
_view = new WrappedView(_source);
}
public object Source
{
get { return _source.Source; }
set { _source.Source = value; }
}
public object UnderlyingSource
{
get { return _source; }
}
public IWrappedCollectionView View
{
get
{
if (_source.View == null)
return null;
return _view;
}
}
private class WrappedView : IWrappedCollectionView
{
private readonly CollectionViewSource _source;
public WrappedView(CollectionViewSource source)
{
_source = source;
}
public bool MoveCurrentTo(object item)
{
return _source.View.MoveCurrentTo(item);
}
public bool MoveCurrentToPosition(int position)
{
return _source.View.MoveCurrentToPosition(position);
}
public bool IsCurrentAfterLast
{
get { return _source.View.IsCurrentAfterLast; }
}
public bool MoveCurrentToFirst()
{
return _source.View.MoveCurrentToFirst();
}
public bool IsCurrentBeforeFirst
{
get { return _source.View.IsCurrentBeforeFirst; }
}
public bool MoveCurrentToLast()
{
return _source.View.MoveCurrentToLast();
}
public bool MoveCurrentToNext()
{
return _source.View.MoveCurrentToNext();
}
public bool MoveCurrentToPrevious()
{
return _source.View.MoveCurrentToPrevious();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment