Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements Carousel control and sample carousel page #712

Merged
merged 30 commits into from
Mar 20, 2017

Conversation

Mimetis
Copy link
Contributor

@Mimetis Mimetis commented Dec 13, 2016

Implementing a first version of the Carousel control.

@dnfclas
Copy link

dnfclas commented Dec 13, 2016

Hi @Mimetis, I'm your friendly neighborhood .NET Foundation Pull Request Bot (You can call me DNFBOT). Thanks for your contribution!

In order for us to evaluate and accept your PR, we ask that you sign a contribution license agreement. It's all electronic and will take just minutes. I promise there's no faxing. https://cla2.dotnetfoundation.org.

TTYL, DNFBOT;

@dnfclas
Copy link

dnfclas commented Dec 13, 2016

@Mimetis, Thanks for signing the contribution license agreement so quickly! Actual humans will now validate the agreement and then evaluate the PR.

Thanks, DNFBOT;

@deltakosh deltakosh added this to the v1.4 milestone Jan 23, 2017
namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
/// A page that shows how to use the DropShadowPanel control.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be DropShadowPanel control :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah ah correct :) Copy / Paste "is not" a friend !!

xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:local="using:Microsoft.Toolkit.Uwp.SampleApp.SamplePages"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you need to use XamlStyler in Xaml pages

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TransitionDuration="{Binding TransitionDuration.Value, Mode=OneWay}"
Depth="{Binding Depth.Value, Mode=OneWay}"
MaxVisibleItems="{Binding MaxVisibleItems.Value, Mode=OneWay}"
x:Name="carouselControl"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name Should start with Capital letter CarouselControl

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done .

@IbraheemOsama
Copy link
Member

Why I can't move using keyboard ? I guess it will be helpful as it was the first thing I do when I browse images on any slider is to move using keyboard arrows.
What do you think ?

@IbraheemOsama
Copy link
Member

When I change the selected item using touch or mouse, the SelectedIndex slider in the properties Window became useless as when manipulating it nothing happens

mc:Ignorable="d">



Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why all this spaces ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx, I have made the corrections

using Microsoft.Toolkit.Uwp.SampleApp.Models;
using System;
using System.Collections.ObjectModel;
using System.Linq;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The using statements need to be rearranged and the non used need to be removed.

datas.Add(new CarouselData { BitmapImage = new BitmapImage(new Uri("ms-appx:///Assets/Photos/NovemberHikeWaterfall.png", UriKind.Absolute)), Title = "14" });
datas.Add(new CarouselData { BitmapImage = new BitmapImage(new Uri("ms-appx:///Assets/Photos/Owl.png", UriKind.Absolute)), Title = "15" });

this.Datas = datas;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove this keyword as it is useless.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, to be honest, using this or not is a "coding style" and I use "this" every time I can, to make my code the most readable as possible.
I know we can have a long long debate about this.
But anyway, is adding "this" or not, Something so important in this case ? :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is important as it is part of our guideline :) we need to keep the same coding style for the entire project

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will delete all the "this" keywords if they're not necessary :)

using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the unused namespaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

{
public class Carousel : Canvas
{
private double initialOffset;
Copy link
Member

@IbraheemOsama IbraheemOsama Jan 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not using the Standard library rules for documentations and naming conventions

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last version has changed, can you take a look on it ?

@IbraheemOsama
Copy link
Member

@Mimetis up ?

@nmetulev nmetulev mentioned this pull request Feb 14, 2017

if (this.SelectedIndex == index)
{
this.SelectedIndex = this.SelectedIndex == 0 ? 0 : this.SelectedIndex - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the last item is removed, SelectedIndex should become -1. Here it would end up with 0.

@deltakosh
Copy link
Contributor

Hey @Mimetis,do you think you can implement the requested changes? Thank you :)


<Border Margin="0">

<controls:Carousel ItemsSource="{Binding Datas}" Background="{StaticResource Brush-Grey-05}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure xaml in the bind file matches the xaml in the actual page

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

<controls:Carousel.ItemTemplate>
<DataTemplate>
<Grid >
<Grid.RowDefinitions>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for the Rows or even the Grid itself. Template can just be the Image

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, corrected

@@ -0,0 +1,52 @@
<Page x:Class="Microsoft.Toolkit.Uwp.SampleApp.SamplePages.Carousel"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class name should have the 'Page' suffix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, corrected

<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image Width="200"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, corrected

DataContext = propertyDesc.Expando;
}

var datas = new ObservableCollection<CarouselData>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Images can be obtained from the PhotosDataSource class.

carouselControl.ItemsSource = await new Data.PhotosDataSource().GetItemsAsync()

All of the images were actually changed from pngs to jpgs recently

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for the tips, I changed the way sample work :)

this.ManipulationMode = ManipulationModes.All;
this.IsHitTestVisible = true;

this.SubscribePropertyChanged("ItemsSource", OnCarouselPropertyChanged);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use RegisterPropertyChangedCallback method to handle the ItemsSource changing, or listen to the Items.VectorChanged event to know when items have been added/removed/changed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, corrected

{
base.PrepareContainerForItemOverride(element, item);

if (this.ItemTemplate == null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not create a new CarouselItem to handle displaying the content and handle the transform? Then each CarouselItem could have the dependency properties required for render transform

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to create a specialized item (CarouselItem) for each items.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why? I think it could simplify some things

Copy link
Contributor Author

@Mimetis Mimetis Mar 2, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easier for the developer to submit an ItemTemplate based on a ContentControl than a CarouselItem, in my opinion :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How so? The fact that a ListView uses a ListViewItem does not change how a user defines an ItemTemplate

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh Yes, my bad you're right on this point.
Anyway, adding a CarouselItem implies adding a new control class and a new style.
I want to have something the most simpliest.
Adding a CarouselItem is, in my point of view, a good thing if we need events and so on on each items.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the transform/animation stuff was to really be improved (in a future version), it should be changed to use Composition. As far as I understand, Composition does not work well with normal DPs, so introducing CarouselItems now and controlling them through DPs might go into the wrong direction. Just my 2 cents...


namespace Microsoft.Toolkit.Uwp.UI.Controls
{
public class CarouselPanel : Panel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason the functionality of this class is not in the Carousel control itself?
What happens if I use a CarouselPanel directly in my xaml? What happens if I use it as the panel for a ListView?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It won't work.
This CarouselPanel is needed because you want an ItemsControl.
That's why, when you create an object inheriting from ItemsControl, if you follow the guidelines and how it's implemented in object like ListView, you should create an ItemsPanel.
For Carousel , the problem is that the only ItemsTemplate that works is the CarouselPanel.
And in the other side, the only ItemsControl that could work with a CarouselPanel is the Carousel control.
Maybe in a next release, we could try to resolved this design problem :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is my understanding as well. On top of this, if you want to layout items, Panel is the way to go. However, Panel can't be focused and can't get keyboard/controller events, so you need a Control (such as the ItemsControl). I ran into the same "issue" in my implementation, and I believe this is by design

continue;
}

this.Carousel.SelectedIndex = i;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No guarantee that the panel will be placed within a Carousel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I Change the Carousel getter to raise an error if we use this panel in other ItemsControl

{
var position = e.GetPosition(this);

for (int i = 0; i < this.Children.Count; i++)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there was a CarouselItem, it could listen to tap events and set itself as the selected item. The Carousel could listen to the CarouselItem changing this and set it's own property.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe.
Don't remember exactly why I made it like this, but in my opinion:

  1. I don't want CarouselItem, to let more flexibility to developers
  2. I think I made it like that because of Virtualization (less events to subscribe)

@skendrot
Copy link
Contributor

skendrot commented Mar 2, 2017

Started a review, but after reviewing the CarouselPanel I stopped to think, "Can this be a ListViewBase?" Is there any reason not to make this a ListViewBase control? It's possible that the manipulation code can be replaced by using a ScrollViewer and setting the Vertical and HorizontalSnapPointsType.
Not sure if placement would work correctly, but maybe having a CarouselItem could help with that.

Thoughts?

@Mimetis
Copy link
Contributor Author

Mimetis commented Mar 2, 2017

I think ListViewBase raise too many events and set to many properties in my opinion.
I prefer to let the developer used it as an ItemsControl :)
To keep the control as simple as possible I think ItemsControls is enough ?

@deltakosh
Copy link
Contributor

@nmetulev @IbraheemOsama Do you mind guys updating your reviews based on latest commits?
We will close 1.4 on 3/21

@@ -68,11 +68,17 @@
<WebView Name="webView"
Grid.Row="0"
Visibility="Collapsed" />
<Button x:Name="PrintButton"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

woot?

@deltakosh
Copy link
Contributor

@nmetulev your last commit is suspicious :)

@nmetulev
Copy link
Contributor

Should be good now @deltakosh

@Mimetis, I updated the focus to work for Xbox better and added the automation property. However, working on the automation property I realized that we should change how focus works on the control so it focuses on each item instead of the control itself. Could you take a look at it and see what it would take to do that?

For me, that and the sudden jump to an item on inertial scrolling are the last two things that should be fixed.

@deltakosh
Copy link
Contributor

Ping @Mimetis
We plan to close on 3/21 and I would love to merge this PR before

@Mimetis
Copy link
Contributor Author

Mimetis commented Mar 15, 2017

I'm currently working on the "sudden jump" behavior. But it's ... complicated :)
And the automation focuses is in my backlog

@deltakosh
Copy link
Contributor

Do you think you can make it before 3/21?

@Mimetis
Copy link
Contributor Author

Mimetis commented Mar 15, 2017

I really dont know.
I tried severals solutions an no one is correct.
For instance it's (as far as I know) nearly impossible to modify inertia or delta translation during a Manipulation, that's why we use an animation.

And for the tab control, I have to make some implementations, to see if the behavior is correct.

So, for now, if those requests are mandatory, the response is No :)

For instance the control is actually working pretty well, maybe we could schedule these improvements for a next version ?

@nmetulev
Copy link
Contributor

Just added code to change the tabstop to be on the items and use arrow focus. I'll take a look at the inertia if I have time tomorrow; otherwise I'll let you know.

@Mimetis
Copy link
Contributor Author

Mimetis commented Mar 16, 2017

Thx @nmetulev I just tried your solution about tabstop and it's working pretty well. Nice job !
About inertia and the sudden jump, let me know if you have any idea :)

@deltakosh
Copy link
Contributor

We will check for the sudden jump. can you create the documentation?

@nmetulev
Copy link
Contributor

I spent a bit of time investigating the sudden jump, and tried to resolve it by canceling the inertia when detected and running the animation to the closes item where the inertia would have ended (by calculating the speed and deceleration of the inertia). It seems to be promising, but it still has some issues which I don't think I can resolve this week.

My proposal is to merge the PR as soon as the docs are added, and we open a bug for this issue?

I pushed my work so far here. @Mimetis , could you take a look and see if this make sense? You know the code much better, and I'm hoping my experimentation might give you an idea :)

@deltakosh
Copy link
Contributor

perfectly fine with that. I'll merge as soon as we have a doc

@Mimetis
Copy link
Contributor Author

Mimetis commented Mar 19, 2017

Thx @nmetulev for your awesome work !
I'had already test a solution like yours, based on the Velocities and Inertia.
The problem now is that we don't have inertia behavior anymore and the animation, with gesture manipulation, is not as smooth as it was before.
An other problem, is the behavior when you make a really small manipulation. Try to just apply a minimal animation of 2 ou 3 pixels to left or right, you will see the item "jump to the next".

It's an interesting work, and I think we should work on it more if we want to release something based on the inertia interruption.

I will work right now on the documentation, since this problem won't affect the documentation, but we have to decide what kind of manipulation behavior we want

@deltakosh
Copy link
Contributor

That's what I call a doc:)

@deltakosh deltakosh merged commit f5cb104 into CommunityToolkit:dev Mar 20, 2017
@deltakosh
Copy link
Contributor

I'm merging now. If someone found something wrong please open an issue

@deltakosh
Copy link
Contributor

Congrats @Mimetis !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants