Creating a Sorted Collection View in WinRT - windows-8

Has anyone had a go at creating a view that sorts a collection? The ICollectionView interface is present, and it claims to have the same responsibilities as its WPF / SL counterpart (sorting, paging, filtering), however, unless I have missed something, there are no sort
methods / properties on the interface.
I would be interested to find out how to take a collection of items then sort them via a view in WinRT.
Note, I know I can do this manually, however, I want to see how a sorted collection interacts with the WinRT theme transitions that appear to add visual effects when sorting is performed.

Unfortunately, there's no support for sorting a collection view in Win8 (nor filtering or grouping). The only way to do this is to manipulate the data source directly, then assign it to Source property.
This has been discussed as an improvement for the post-Win8 timeframe. Wish I had better news :)

Linq seems to be the suggested way now that Sort and Filter have gone AWOL.
So you could adopt something like this in your model:
private MyDataSourceProvider dataSource;
private ObservableCollection<MyType> sortedDataBackingField;
public ObservableCollection<MyType> SortedData
{
get
{
return sortedDataBackingField;
}
set
{
sortedDataBackingField = value;
NotifyPropertyChanged("SortedData");
}
}
public void SortByName()
{
SortedData = new ObservableCollection<MyType>(dataSource.Entities.OrderBy(
entity => entity.Name));
}
public void SortByAge()
{
SortedData = new ObservableCollection<MyType>(dataSource.Entities.OrderBy(
entity => entity.Age));
}
Hook SortByName and SortByAge up to your UI in the pattern of your choice, and simply bind to the SortedData property:
<ItemsControl ItemsSource=”{Binding SortedData}”/>
Edit: With reference to transitions, you should find that this approach will trigger the AddDeleteThemeTransition for the items that you've sorted; just add something like this inside the ItemsControl:
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<AddDeleteThemeTransition></AddDeleteThemeTransition>
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>

Related

Struggling With MVVM

I have a class named osmAppBarButton that inherits from AppBarButton (UWP) to which I have added a dependency property named ButtonState. (Enum Normal, Dim, Bright, Flash)
I have a Style used on all my osmAppBarButtons, that uses a DataTriggerBehavior to check the ButtonState and select the appropriate VisualState.
I was rather please with myself, as DPs and the VisualStateManager are all new to me. Then I hit a problem..
How can I change an osmAppBarButton's ButtonState from the ViewModel without breaking MVVM ? I thought about having a VM property for the ButtonState of each button in my view, but that would imply that the VM would have some knowledge of the View.
I think that the answer may lie with Attached Behaviours, but I haven't found an example that suits.
Any ideas ?
The way you get values from a viewmodel property to a dependency property is to use a Binding. Certainly not an attached behavior; I'm sure you could find some way to do that with an attached behavior, but just use a Binding.
`The viewmodel must implement INotifyPropertyChanged, and it must be the DataContext for the view where the appbar button lives, and you must not be shooting yourself in the foot by binding DataContext to something random in some parent of the appbar button.
Give the viewmodel a public property that raises PropertyChanged when its value changes. Bind to that property.
An enum like ButtonState with Normal, Dim, Bright, Flash values isn't the kind of thing a viewmodel should be aware of in a "proper" MVVM implementation. This isn't actually a silly point, either. I would suggest having the viewmodel expose its state through properties that express the viewmodel's state in its own terms (I could give you an example, if I knew what you were doing here). Maybe the viewmodel has a State that can be Normal, Busy, Error, Waiting -- those might map onto various ButtonState values. "Error" is a state of the viewmodel. "Flash" is one of many ways a view might choose to communicate a given viewmodel state to the user.
If the viewmodel expresses the relevant state using one or more properties with types other than ButtonState, you'd write a converter -- maybe a multiconverter -- to translate all that into a ButtonState value.
But it won't be the end of the world if your learning program uses ButtonState in a viewmodel, and that'll be simpler. So bind it to this:
private ButtonState _fooBarButtonState = ButtonState.ItsComplicated;
public ButtonState FooBarButtonState {
get { return _fooBarButtonState; }
set {
if (value != _fooBarButtonState) {
_fooBarButtonState = value;
OnPropertyChanged(nameof(FooBarButtonState));
}
}
}
XAML:
<local:osmAppBarButton
ButtonState="{Binding FooBarButtonState}"
/>
But if you'd like to go with my suggestion to use a different state enum in the viewmodel, converters are quite trivial to write. Let me know if you hit a snag, but if you got a dependency property and viewstates working, you'll get it.

WinrtXamlToolkit TreeView ItemContainerStyleSelector not firing

I am using the TreeView control from the WinrtXamlToolkit in a uwp app. I want to apply a different style to some TreeViewItems depending on a conditon so I created a class, TreeViewItemStyleSelector which derives from StyleSelector and I override the SelectStyleCore function.
public Style ResourceStyle { get; set; }
public Style ClassroomStyle { get; set; }
protected override Style SelectStyleCore(object item, DependencyObject container)
{
// control never reaches here.
// logic to apply style
}
Then in xaml I use it like this.
In Page Resources
<StyleSelectors:TreeViewItemStyleSelector ResourceStyle="{StaticResource AStyle}" ClassroomStyle = "{StaticResource BStyle}"/>
And later in the page.
<wxtControls:TreeView ItemsSource="{Binding StructureViewModels}" ItemContainterStyleSelector="{StaticResource TreeViewItemStyleSelector}" />
The problem is that the SelectStyleCore override is never called. Does anybody know why?
I am not yet sure what's the reason this doesn't work, although I have some theories. One is - this was never implemented. Perhaps at least at the root level it should work because it's an ItemsControl, but because of the way it's implemented (hierarchically) - the ItemContainerStyleSelector would have to be forwarded from the TreeView to the TreeViewItems, which it isn't.
I haven't had a chance to try to reproduce it yet, but if I were to try to fix it or work around it - I would first try forwarding that property in HeaderedItemsControl.cs - roughly where it says "// Note: this is where we would apply the HeaderTemplateSelector (...) (if implemented)". The alternative (if you don't want to modify the toolkit's code) might be to specify the template for the TreeViewItem and in the template - use a StyleSelector on template parts you want to be different for different data items.

Setting the initial selected item when binding to a ListView's SelectedItem property

I have a Xamarin.Forms xaml page in which I am using a ListView to allow the user to pick a single item out of a list. I have bound the ListView's SelectedItem property to a property on my ViewModel and this works fine. As soon as the user changes the selected item the property in my viewmodel updates as well.
However, even though I initially set the property in my ViewModel to one of the values from the list, when the page loads the ListView's SelectedItem property is null, which in turn sets the ViewModel property to null as well.
What I need is the other direction, I want the ListView to initially select the item that i've set in the VM property.
I can hack together a solution by writing extra code in the code behind file to explicitly set the initial selected item, but this introduces additional properties and complexity and is quite ugly.
What is the correct way to set the initial selected item of a ListView who's selected item is bound to a viewmodel property?
-EDIT-
I was asked to provide the code that I'm using for my binding.
It's very simple, standard:
<ListView x:Name="myList" ItemsSource="{Binding Documents}" SelectedItem="{Binding SelectedDocument}">
the view model that is set as the binding context for the listview is instantiated before the page is created and looks like this:
public class DocumentSelectViewModel : ViewModelBase
{
private Document selectedDocument;
public List<Document> Documents
{
get { return CachedData.DocumentList; }
}
public Document SelectedDocument
{
get { return selectedDocument; }
set { SetProperty(ref selectedDocument, value);
}
public DocumentSelectViewModel()
{
SelectedDocuement = CachedData.DocumentList.FirstOrDefault();
}
}
SetProperty is a function which simply rasies the INotifyPropertyChanged event if the new value is different from the old one, classical binding code.
I am a little rusty on XAML but don't you need to make the binding two-way?
E.G.
{ Binding SelectedDocument, Mode=TwoWay }
As long as the SelectedDocument property change raises the INotifyPropertyChanged event then you should get the desired effect.
If you replace
public DocumentSelectViewModel()
{
SelectedDocument = CachedData.DocumentList.FirstOrDefault();
}
By
public DocumentSelectViewModel()
{
SelectedDocument = Documents.FirstOrDefault();
}
Does it work for you ?
I had a similar problem that has been resolved this way...
You can use ctor DocumentSelectViewModel for set initial value. Honestly I dont like to make some job in ctor block but Xamarin.... You dont need DocumentSelectViewModel method. It will work.
public DocumentSelectViewModel ()
{
SelectedDocument = Documents[0]; //or any your desired.
}

fluent nhibernate polymorphism. how to check for type of class

I have an Icon which has a Content (one to one) relationship.
public class Icon
{
public virtual Content Content {get; set;}
}
By default, it is lazy loaded which is what I want.
However, at some point in the code, I need to check what kind of Content is, Content being polymorphic, something like
if(icon.Content is TextContent)
{
...
}
Icon is part of another association and it is automatically obtained by the NHibernate, I do not get it manually.
What is the recommended way of checking for the actual type in this situation?
I can have a specific property like ContentType which will be an enum in order to identify the actual content type, but I am looking to know if there's a different way.
If you want to do that kind of check, you have to remove the proxy from the property.
There is a few ways to do it:
If you have access to the session call:
session.PersistenceContext.Unproxy(icon.Content);
Implement a virtual method (in a base class if possible) that forces the removal of the proxy by returning the instance with the proper type.
public virtual U As<U>() where U : YourType {
return this as U;
}
Disable the lazy initialization of the property.
This is very similar to another recent question.
To add to csanchez's list, a fourth method is to add a Self property to the Content base class that returns the un-proxied type:
public virtual void Self
{
get { return this; }
}
And a fifth method is to use 'lazy="no-proxy"` in the mapping as described on Ayende's blog.
Thanks for the suggestions but meanwhile I found an interesting solution, better I think.
Using the Visitor pattern, I can define an IconContent visitor and pass an Action to be executed to it.
For example, suppose there is a TextContent and an ImageContent, it will be something like this:
IconContentVisitor.Func(()=> { Console.WriteLine("this is TextContent"; }, ()=> { Console.WriteLine("this is ImageContent"));
Idea came from here: http://mookid.dk/oncode/archives/991

robotlegs: I have 2 views and mediators that have in common 1 thing how can I DRY it?

I have 2 views that show lists that then uses a mediator to get data. but I want in some way to DRY it so I don't have to repeat my self 2 times for the same thing. how do I do it?
EDIT1(code):
[SkinPart(required="false")]
public var WOListsDDL:DropDownList;
// in partadded
case WOListsDDL:
// when the selected list is changed in the lists drop down list
WOListsDDL.addEventListener(IndexChangeEvent.CHANGE, _WOListsDDL_changeHandler);
WOListsDDL.dataProvider = new ArrayCollection();
WOListsDDL.labelField = 'title';
break;
//
protected function _WOListsDDL_changeHandler(event:*):void{
_debug('List selection changed handler.');
_getContentsForList();
}
protected function _getContentsForList():void{
_debug('Getting list items.');
getItemsSignal.dispatch({key: getSelectedList()._key, itemType: 'item'});
}
public var getItemsSignal:GetItemsSignal = new GetItemsSignal();
override public function mediatorComplete():void{
getItemsSignal.dispatch({key: tottysAuth.getCurrentUser()._key, itemType: 'list'});
}
// then in my mediator
[Inject] public var getItemsSignal:GetItemsSignal;
override public function onRegister():void{
// view listeners
view.getItemsSignal.add(_getItemsSignalHandler);
}
protected function _getItemsSignalHandler(input:Object):void{
getItemsSignal.dispatch(input);
}
this all for one view-mediator. now I have 2 view-mediators that are doing these tasks. How to make them dry?
Solutions I have:
make a little view containing the dropdown list with a mediator that is listening for the event. in the big components they are listening for a signal in the view of this little component. nothing more. it seems quite well but i don't think is so great
So there is functionality on both the views and the mediators that you'd like not to repeat?
You could put the code you want to reuse in another object and call its methods from your multiple views and mediators. Or you could put it in ancestor classes and extend each of those classes in both your view and your mediator.
Best practice would be to do the former and not the latter.