github

Scroll to any item in your Xamarin.Forms CollectionView from your ViewModel

Scroll to any item in your Xamarin.Forms CollectionView from your ViewModel

If you are working with collections in your app, chances are high you are going to want (or need) to scroll to a specific item at some point. CollectionView has the ScrollTo method that allows you to do so. If you are using MVVM in your app however, there is no built-in support to call this method.

My solution

My solution for this challenge consists of following parts:

  • a BindableProperty in an extended CollectionView class to bind the item we want to scroll to
  • a configuration class to control the scrolling behavior
  • a base interface with the configuration and two variants derived from it (one for ungrouped items, one for grouped ones)

Let’s have a look at the ScrollConfiguration class:

public class ScrollToConfiguration
{
    public bool Animated { get; set; } = true;

    public ScrollToPosition ScrollToPosition { get; set; } = ScrollToPosition.Center;
}

These two properties are used to tell our extended CollectionView how the scrolling to the item will behave. The above default values are my preferred ones, feel free to change them in your implementation.

Next, let us have a look at the base interface:

public interface IConfigurableScrollItem
{
    ScrollToConfiguration Config { get; set; }
}

Then we will define two additional interfaces which we are going to use later in our ViewModel:

    public interface IScrollItem : IConfigurableScrollItem
    {
    }

    public interface IGroupScrollItem : IConfigurableScrollItem
    {
        object GroupValue { get; set; }
    }

For a non-grouped CollectionView, we just need to implement IScrollItem. If we have groups, we’ll use IGroupScrollItem to add an object that identifies the group (following the Xamarin.Forms API here).

Extending CollectionView

Let’s connect the dots and implement an extended version of the CollectionView – to do so, create a new class and derive from it. I named mine CollectionViewEx (ingenious, right?).

To wrap things up, we now add a BindableProperty with a PropertyChanged handler to our CollectionViewEx that we can bind against, and which is, most importantly, calling the ScrollTo method of CollectionView.

Here is the full class:

public class CollectionViewEx : CollectionView
{
    public static BindableProperty ScrollToItemWithConfigProperty = BindableProperty.Create(nameof(ScrollToItemWithConfig), typeof(IConfigurableScrollItem), typeof(CollectionViewEx), default(IConfigurableScrollItem), BindingMode.Default, propertyChanged: OnScrollToItemWithConfigPropertyChanged);

    public IConfigurableScrollItem ScrollToItemWithConfig
    {
        get => (IConfigurableScrollItem)GetValue(ScrollToItemWithConfigProperty);
        set => SetValue(ScrollToItemWithConfigProperty, value);
    }

    private static void OnScrollToItemWithConfigPropertyChanged(BindableObject bindable, object oldValue, object newValue)
    {
        if (newValue == null)
            return;

        if (bindable is CollectionViewEx current)
        {
            if (newValue is IGroupScrollItem scrollToItemWithGroup)
            {
                if (scrollToItemWithGroup.Config == null)
                    scrollToItemWithGroup.Config = new ScrollToConfiguration();

                    current.ScrollTo(scrollToItemWithGroup, scrollToItemWithGroup.GroupValue, scrollToItemWithGroup.Config.ScrollToPosition, scrollToItemWithGroup.Config.Animated);

            }
            else if (newValue is IScrollItem scrollToItem)
            {
                if (scrollToItem.Config == null)
                    scrollToItem.Config = new ScrollToConfiguration();

                    current.ScrollTo(scrollToItem, null, scrollToItem.Config.ScrollToPosition, scrollToItem.Config.Animated);
            }
        }
    }
}

Let’s go through the code. The BindableProperty implementation should be common to most of us (if not, read up the docs). The most important part happens in the PropertyChanged handler.

By allowing the value of the BindableProperty to be null, we can reset the item and scroll to the same item again if necessary. Because IScrollItem as well as IGroupScrollItem derive from IConfigurableScrollItem, we can handle them both in one method. To make sure there is a default ScrollToConfiguration, I am checking the Config property for null – in case it is (because I forgot it), there is at least the default. In the end, I am scrolling to the Item in the CollectionView using the ScrollTo method.

The ViewModel(s) and Binding

Here is one of the (simple) ViewModels from the sample application for this post:

public class ItemViewModel : ViewModelBase, IScrollItem
{
    public ItemViewModel()
    {
        this.Config = new ScrollToConfiguration();
    }

    public string Text { get; set; }

    public int Number { get; set; }

    public ScrollToConfiguration Config { get; set; }
}

Now in the parent ViewModel, we just add another property that we can use to bind against the CollectionViewEx‘s ScrollToItemWithConfig property. The Binding is straight forward:

<controls:CollectionViewEx
    Grid.Row="3"
    Margin="6"
    ItemsSource="{Binding ScrollableItems}"
    ScrollToItemWithConfig="{Binding ScrollToVm}"
    SelectedItem="{Binding SelectedItemVm, Mode=TwoWay}"
    SelectionMode="Single">
    <controls:CollectionViewEx.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Label Margin="5,10" Text="{Binding Text}" />
            </Grid>
        </DataTemplate>
    </controls:CollectionViewEx.ItemTemplate>
</controls:CollectionViewEx>

The result of this whole exercise looks like this:

Conclusion

Even if the CollectionView control in Xamarin.Forms provides a whole bunch of optimized functionalities over ListView, there are some scenarios that require additional work. Luckily, it isn’t that hard to extend the CollectionView. Scrolling to a precise ViewModel is easy with the code above. Of course, I created also a sample Github repo.

As always, I hope this post will be helpful for some of you.

Until the next post, happy coding, everyone!
Posted by msicc in Dev Stories, Xamarin, 1 comment
How to host a code file on Github as Gist to use in your application

How to host a code file on Github as Gist to use in your application

What the h*** is a Gist?

In case you never heard of Gist, it is an easy to use way to share code files hosted by Github. Everyone with a user account can use this feature, and now that also the premium features are free (thanks to the acquisition by Microsoft), you can even share them secretly.

Where do I find my Gists?

This one is for the beginners. If you know this already, move on. Once you have logged into your Github account, click on your user name. This will open a menu where you can see an option called ‘Your gists’. Once you clicked that one, you will see a page similar to mine (maybe with no gists in it):

gist_overview_gists

How to create a new Gist?

Well, that’s pretty easy. You just click on the ‘+’-button besides your user avatar in the top right corner:

gist_menu_add_new

This will bring up a new gist window. Enter your description, file name and fill in the content of your file or even add more files and hit the ‘Create public gist’ button to create your new gist. If you intend to host multiple files in your gist, please note that you will need the following steps on every single file you add (as each one has its own url).

gist_add_new

How to use this Gist in my app?

Luckily, both files in Github repos as well as in gists can be viewed in the so called ‘Raw’ view. You will find a corresponding button on every code file in the top right corner. Click on it, and you will see a plain-text representation (here is a sample from the one that led to this block post. It is styled by a browser extension that makes json more readable (every developer should already have one of this type installed, btw)):

gist_raw_view

Now we are close to be able to fetch this file into our applications. If you are sure that this file will never change, just use this file. If you know that this file is subject for future changes, you will need to perform a little trick.

Getting always the latest version of our Gist

If you analyze the url, you will notice that there is a unique id between the ‘raw’ part and the file name:

gist_remove_this_id

This id represents the current revision of your Gist. To make sure we always get the latest version of our gist, we need to remove this id. The url must end with ‘raw/yourfile.extensions‘, as you can see here:

gist_always_latest_revision_url

This way, you can update the file and implement an update mechanism into your app that fetches always the latest revision of that file. To fetch the file content into your app, you just need to perform a GET request against that url, without the overload of using Github’s API.

Conclusion

Instead of hosting configuration or data files on a private web server, one can utilize existing infrastructure like the one of Github. Like always, I hope this post will be helpful for some of you.

Until the next post, happy coding, everyone!
Posted by msicc in Dev Stories, Xamarin, 1 comment
2018 in review – Focus on Xamarin, RIP UniShare, the rise of crypto and blockchain

2018 in review – Focus on Xamarin, RIP UniShare, the rise of crypto and blockchain

This year, I had some rough time to keep me motivated on writing blog posts. In the early months, I was keeping my target to write about Xamarin Forms and my implementations, but I slowly lost pace around the summer.

Xamarin posts

Within the first half of the year, I was keeping a pretty constant 2 week frame for new blog posts, targeting Xamarin and Xamarin Forms. I touched several topics (some of which may be obsolete since Xamarin Forms 3.x). Here is a short recap:

The rise of crypto and blockchain

Since 2017, I was loosely following the area of crypto currencies and blockchain. This year, however, marks the beginning of a deeper dive into the blockchain area – and of course also into crypto currencies. I am not advising anyone to invest any money into crypto currencies, but there are certain projects out there that are really interesting. Two of them are social networks, similar to Tumblr: Steemit and Trybe. While Steemit is running on its own blockchain, Trybe is utilizing the EOS blockchain. Sadly, the .NET world seems to be widely ignored, so I stepped down a bit from posting on those two. I also tested several other networks running on or with blockchain, but none of them took me like the two mentioned above. If you want to learn more about the crypto currencies/projects I am interested in, just head over to my crypto page.

Open Source

Even if I did not made a lot of sound around it, I have worked on some libraries this year. I am not going into detail on every one, just head over to my Github:

I am currently working on another library (targetting crypto payments) – I will write about it once it is ready to be used in your projects.

RIP UniShare

One of the sadest moments this year was the death of UniShare, my most popular Windows (Phone) app. Long story short, due to some changes Facebook made to their API, I had to take UniShare to its funeral at the end of October. Read more about it here.

Looking forward to 2019

In 2019, I will continue my journey within the crypto/blockchain world. Like I wrote above, I am working on a crypto related project at the moment, which I hope to have ready in the early weeks of 2019. One of my other projects, WindowsUnited, will be taken over by another developer in 2019 (because he can invest more time into their official apps and work form them more ore less exclusively). This will free up some recsources, which I am trying to invest in my other projects and the rise of my blogging pace (again).

Thanks to all of you for reading my posts this year. I hope you’ll be with me in 2019 as well. I wish all of you a good arrival in 2019 and a happy new year once it arrives.

Until the next post, happy coding, everyone!

Posted by msicc in Editorials, 0 comments