binding

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
Code Snippets for Xamarin.Forms BindableProperty

Code Snippets for Xamarin.Forms BindableProperty

If you haven’t heard about the #XamarinMonth before, you should either click on the hashtag or read Luis’ blog post where he introduces the topic. At the end of his post, you will also find a link to all the contributions.

Why Code Snippets?

Code snippets make it easier to reuse code you write repeatedly during your dev life. For Xamarin Forms, there are no “built-in” snippets, so I decided to start creating my own snippets some time ago. If you want to get started, have a look at the docs.

The Snippets

If you ever wrote a custom control or an Effect for Xamarin Forms, chances are high you also used the BindableProperty functionality. I got tired of remembering the syntax, so I decided to write some snippets for it:

  • BindableProperty (bindp)
  • BindableProperty with PropertyChanged handler (bindppc)
  • Attached BindableProperty (bindpa)
  • Attached BindableProperty with PropertyChanged handler (bindpapc)

You can download all of them from my Github repo.

Once you insert (write shortcut, Tab, Tab) the snippet, you just need to define the name of the property as well as its type and hit enter – that’s it.

Tip: To make sure that the snippets show up with IntelliSense, go to Tools/Options, find the Text Editor section followed by the C# entry. Under IntelliSense, find the option for ‘Snippet behavior‘ and choose ‘Always include snippets‘.

Conclusion

Snippets can save a lot of time. Luckily, the implementation is not that difficult (see docs link above). As always, I hope this post is helpful for some of you.

Until the next post, happy coding, everyone!
Posted by msicc in Dev Stories, Xamarin, 0 comments
Xamarin Forms, the MVVMLight Toolkit and I: EventToCommandBehavior

Xamarin Forms, the MVVMLight Toolkit and I: EventToCommandBehavior

Often, we want to/need to know when views throw certain events. However, due to using the MVVM pattern, our application logic is separated from the view. There are several ways to get those events into our ViewModel while keeping it separated from the views. One of those is using an interface, which I showed you already in my blog post about navigation in Xamarin.Forms with MVVMLight.

Another way is the good old EventToCommand approach. Some of you might have used this approach already in WPF and other .NET applications. Xamarin.Forms has them too, this post will show you how to implement it.

Xamarin.Forms Behaviors

In Windows applications like WPF or UWP, we normally use the Interactivity namespace to use behaviors. Xamarin.Forms however has its own implementation, so we need to use the Behavior and Behavior<T> classes. All controls that derive from View are providing this BindableProperty, so we can use Behaviors in a lot of scenarios. Until the new XAML Standard is finally defined, we have to deal with this.

EventToCommandBehavior

Xamarin provides a nearly ready-to-use EventToCommandBehavior implementation and an quite detailed explanation (which is why I won’t go into details on that). The implementation has two part – the BehaviorBase<T>implementation and the EventToCommandBehavior implementation itself.

While we are able to use the BehaviorBase<T> implementation as is, we have to do some minor changes to the EventToCommandBehavior to enable a few more usage scenarios.

The first change we need to make is to derive Xamarin’s EventToCommandBehavior sample from VisualElement instead of View. This way, we can also use the behavior on controls that do not derive from View, especially in Pages. Pages do not derive from View, but they do from VisualElement (like Viewdoes, too). You need to change the Type also on the parameter of the OnAttachedTo and OnDetachingFrom methods in this case (which are the other two changes we need to do).

The rest of the implementation is basically the same like in the Xamarin sample and works quite well.

To show you a simple sample in Action, we are using the Appearing and Disappearing events to attach them via the behavior into our ModalPageViewModelon the ModalPage we integrated before. This way, you won’t need the IViewEventBrokerService I showed you in my post on navigation and modal pages. It is up to you to choose the way you want to go along, both ways are fully respecting the MVVM pattern.

Implementation

The implementation has two parts. As we want to handle the events in a Command, the first step to take is to implement two Commands in the corresponding ViewModel. I am using a base implementation (in my apps and also in this sample), so I am going to implement the Commands there. This way, every derived ViewModel can bind to this Command. Additionally, I am using a Execute...Command method and a CanExecute boolean method, which can both be overriden in derived ViewModels to implement the code to execute. Let’s have a look at the code:

public RelayCommand ViewAppearingCommand => _viewAppearingCommand ?? (_viewAppearingCommand = new RelayCommand(ExecuteViewAppearingCommand, CanExecuteViewAppearingCommand));

public virtual void ExecuteViewAppearingCommand()
{

}

public virtual bool CanExecuteViewAppearingCommand()
{
    return true;
}

public RelayCommand ViewDisappearingCommand => _viewDisappearingCommand ?? (_viewDisappearingCommand = new RelayCommand(ExecuteViewDisappearingCommand, CanExecuteViewDisappearingCommand));

public virtual void ExecuteViewDisappearingCommand()
{

}

public virtual bool CanExecuteViewDisappearingCommand()
{
    return true;
}

The second part is the XAML part, which includes the Binding to the Command properties we just created. The implementation is as easy as these four lines for both events:

    <baseCtrl:XfNavContentPage.Behaviors>
        <behaviors:EventToCommandBehavior EventName="Appearing" Command="{Binding ViewAppearingCommand}"></behaviors:EventToCommandBehavior>
        <behaviors:EventToCommandBehavior EventName="Disappearing" Command="{Binding ViewDisappearingCommand}"></behaviors:EventToCommandBehavior>
    </baseCtrl:XfNavContentPage.Behaviors>

That’s it, if you want to attach the behavior only for individual Pages. If you have a base page implementation like I do however, you can automatically attach the event already there to have it attached to all pages:

private void XfNavContentPage_BindingContextChanged(object sender, EventArgs e)
{
    if (this.BindingContext is XfNavViewModelBase)
    {
        this.Behaviors.Add(new EventToCommandBehavior()
        {
            EventName = "Appearing",
            Command = ((XfNavViewModelBase)this.BindingContext).ViewAppearingCommand
        });
 
        this.Behaviors.Add(new EventToCommandBehavior()
        {
            EventName = "Disappearing",
            Command = ((XfNavViewModelBase)this.BindingContext).ViewDisappearingCommand
        });
    }
}

I am attaching the behaviors only if the BindingContextdoes derive from my XfNavViewModelBase. The Command can be set directly in this case, without the need to use the SetBinding method.

These few lines are connecting the Event to the Command, the only thing we need to do is to override the base implementations of the “Execute…Command” methods:

public override async void ExecuteViewAppearingCommand()
{
    base.ExecuteViewAppearingCommand();
    await _dialogService.ShowMessageAsync(this.CorrespondingViewKey, $"from overriden {nameof(ExecuteViewAppearingCommand)}");
}
 
public override async void ExecuteViewDisappearingCommand()
{
    base.ExecuteViewDisappearingCommand();
    await _dialogService.ShowMessageAsync(this.CorrespondingViewKey, $"from overriden {nameof(ExecuteViewDisappearingCommand)}");
}

The above overrides are using the IDialogService you will find in the sample application to show a simple message from which overriden Execute...Command method they are created from.

Converting EventArgs to specific types

Xamarin.Forms has only a few events that have usefull EventArgs. At the time of writing this post, I tried to find valid scenarios where we want to get some things of the events to attach also an IValueConverterimplementation to get this data out of them. Fact is, the only one I ever used is the one from the Xamarin sample – which is a converter that gets the selected Item for a ListView. Because Xamarin.Forms Views already provide most of the properties I ever needed, I was able to solve everything else via Binding. To make this post complete, you can have a look into Xamarin’s sample implementation here.

Conclusion

Hooking into events on the view side of our applications can be done in several ways. It is up to you to choose the route you want to go. With this post, I showed you a second way to achieve this.

If you have some more valid scenarios for using the EventToCommandBehaviorwith a Converter that cannot be solved via Binding directly, I would love to hear them. Feel free to leave a comment here or via social networks. Of course, I updated the sample on Github with the code from this post.

As always, I hope this post is helpful for some of you. Until the next post, happy coding!

Posted by msicc in Android, Dev Stories, iOS, Windows, Xamarin, 3 comments

How to implement a bindable progress indicator (loading dots) for MVVM Windows (8.1) Universal apps

Screenshot (23)

Now that I am on a good way to understand and use the MVVM pattern, I am also finding that there are some times rather simple solutions for every day problems. One of these problems is that we don’t have a global progress indicator for Windows Universal apps. That is a little bit annoying, and so I wrote my own solution. I don’t know if this is good or bad practice, but my solution is making it globally available in a Windows Universal app. The best thing is, you just need to bind to a Boolean property to use it. No Behaviors, just the one base implementation and Binding (Yes, I am a bit excited about it). For your convenience, I attached a demo project at the end of this post.

To get the main work for this done, we are implementing our own class, inherited from the Page class. The latter one is available for Windows as well as Windows Phone, so we can define it in the shared project of our Universal app. To do so, add a new class in the shared project. I named it PageBase (as it is quite common for this scenario, as I found out).

First, we need to inherit our class from the Page class:

public abstract class PageBase : Page

Now that we have done this, we need a global available property that we can bind to. We are using a DependencyProperty to achieve this goal. To make the property reflect our changes also to the UI, we also need to hook into a PropertyChanged callback on it:

        //this DepenedencyProperty is our Binding target to get all the action done!
        public static readonly DependencyProperty IsProgressIndicatorNeededProperty = DependencyProperty.Register(
            "IsProgressIndicatorNeeded", typeof (bool), typeof (PageBase), new PropertyMetadata((bool)false, OnIsProgressIndicatorNeededChanged));

        public static void OnIsProgressIndicatorNeededChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

        }

        //get and send the value of our Binding target
        public bool IsProgressIndicatorNeeded
        {
            get { return (bool) GetValue(IsProgressIndicatorNeededProperty); }
            set { SetValue(IsProgressIndicatorNeededProperty, value); }
        }

The next step we need to do is to find the UIElement we want the progress indicator to be in. To do so, we are going through the VisualTree and pick our desired element. This helper method (taken from the MSDN documentation) will enable us to find this element:

        //helper method to find children in the visual tree (taken from MSDN documentation)
        private static void FindChildren<T>(List<T> results, DependencyObject startNode)
          where T : DependencyObject
        {
            int count = VisualTreeHelper.GetChildrenCount(startNode);
            for (int i = 0; i < count; i++)
            {
                var current = VisualTreeHelper.GetChild(startNode, i);
                if ((current.GetType()) == typeof(T) || (current.GetType().GetTypeInfo().IsSubclassOf(typeof(T))))
                {
                    T asType = (T)current;
                    results.Add(asType);
                }
                FindChildren<T>(results, current);
            }
        }

The method goes through the VisualTree, starting at the point we are throwing in as DependecyObject and gives us a List<T> with all specified Elements. From this List we are going to pick our UIElement that will hold the progress indicator for us. Let’s create a new method that will do all the work for us:

        private void CheckIfProgressIndicatorIsNeeded(DependencyObject currentObject)
        {
        }

Notice the DependencyObject parameter? This makes it easier for us to use the method in different places (which we will, more on that later). Let’s get our list of DependencyObjects from our parameter and pick the first Grid as our desired UIElement to hold the progress indicator:

            if (currentObject == null) return;

            //getting a list of all DependencyObjects in the visual tree
            var children = new List<DependencyObject>();
            FindChildren(children, currentObject);
            if (children.Count == 0) return;

            //getting a reference to the first Grid in the visual tree
            //this can be any other UIElement you define
            var rootGrid = (Grid)children.FirstOrDefault(i => i.GetType() == typeof(Grid));

Now that we have this, we are already at the point where we need to create our progress indicator object.  I declared a class member of type ProgressBar (which needs to be instantiated in the constructor then). This is how I set it up:

            //setting up the ProgressIndicator
            //you can also create a more complex object for this, like a StackPanel with a TextBlock and the ProgressIndicator in it
            _progressIndicator.IsIndeterminate = IsProgressIndicatorNeeded;
            _progressIndicator.Height = 20;
            _progressIndicator.VerticalAlignment = VerticalAlignment.Top;

The final step in the PageBase class is to check if there is already a chikd of type ProgressBar, if not adding it to the Grid and setting it’s Visibility property to Visible if our above attached DependencyProperty has the value ‘true’:

            //showing the ProgressIndicator
            if (IsProgressIndicatorNeeded)
            {
                //only add the ProgressIndicator if there isn't already one in the rootGrid
                if (!rootGrid.Children.Contains(_progressIndicator))
                {
                    rootGrid.Children.Add(_progressIndicator);
                }
                _progressIndicator.Visibility = Visibility.Visible;
            }

If the value is ‘false’, we are setting the Visibility back to collapsed:

            //hiding the ProgressIndicator
            else
            {
                if (rootGrid.Children.Contains(_progressIndicator))
                {
                    _progressIndicator.Visibility = Visibility.Collapsed;
                }
            }

Now that we have this method in place, let’s go back to our callback method we have been hooking into earlier. To reflect the changes that we are throwing into our DependencyProperty,  we are calling our method within the PropertyChanged callback. To do so, we are getting a reference to the PageBase class, which is needed because we are in a static method. Once we have this reference, we are calling our method to show/hide the progress indicator:

        public static void OnIsProgressIndicatorNeededChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            //resolving d as PageBase to enable us calling our helper method
            var currentObject = d as PageBase;

            //avoid NullReferenceException
            if (currentObject == null)
            {
                return;
            }
            //call our helper method
            currentObject.CheckIfProgressIndicatorIsNeeded(d);
        }

That’s all, we are already able to use the global progress indicator. To use this class, you need to do a few things. First, go to the code-behind part of your page. Make the class inherit from the PageBase class:

    public sealed partial class MainPage : PageBase

Now, let’s go to the XAML part and add a reference to your class:

    xmlns:common="using:MvvmUniversalProgressIndicator.Common"

Once you have done this, replace the ‘Page’ element with the PageBase class:

<common:PageBase>
//
</common:PageBase>

After you have build the project, you should be able to set the Binding to the IsProgressIndicatorNeeded property:

    IsProgressIndicatorNeeded="{Binding IsProgressIndicatorVisible}">

If you now add two buttons to the mix, binding their Commands to change the value of the Boolean property, you will see that you can switch the loading dots on and off like you wish. That makes it pretty easy to use it in a MVVM driven application.

But what if we need to show the progress indicator as soon as we are coming to the page? No worries, we are already prepared and need only a little more code for that. In the PageBase class constructor, register for the Loaded event:

            Loaded += PageBase_Loaded;

In the Loaded event, we are calling again our main method to show the progress indicator, but this time we use the current window content as reference to start with:

        void PageBase_Loaded(object sender, RoutedEventArgs e)
        {
            //using the DispatcherHelper of MvvmLight to get it running on the UI
            DispatcherHelper.CheckBeginInvokeOnUI(() =>
            {
                //Window.Current.Content is our visual root and contains all UIElements of a page
                var visualRoot = Window.Current.Content as DependencyObject;
                CheckIfProgressIndicatorIsNeeded(visualRoot);
            });

        }

As we need to reflect changes on the UI thread, I am using the DispatcherHelper of the MvvmLight Toolkit. You can use your own preferred method as well for that. That’s all, If you now test it with setting the IsProgressIndicatorNeeded property in your page directly to ‘True’ in XAML, you will see the loading dots right from the start.

Screenshot (21)

Like always, I hope this is helpful for some of you.

Happy coding!

Download Sample project

Posted by msicc in Archive, 1 comment

How to easily check the pressed keyboard button with a converted event using MVVM (Windows Universal)

In case you missed it, I lately am deeply diving into MVVM. Earlier today, I wanted to implement the well loved feature that a search is performed by pressing the Enter button. Of course, this would be very easy to achieve in code behind using the KeyUpEvent (or the KeyDownEvent, if you prefer).

However, in MVVM, especially in a Universal app, this is a bit trickier. We need to route the event manually to our matching command. There are surely more ways to achieve it, but I decided to use the Behaviors SDK to achieve my goal. The first step is of course downloading the matching extension (if you haven’t done so before). To do so, click on TOOLS/Extensions and Updates in Visual Studio and install the Behaviors SDK from the list:image

The next step we need to do is to add a new Converter (I added it to the common folder, you may change this to your preferred place). As we are hooking up the KeyUpEventArgs, I called it KeyUpEventArgsConverter. After you created the class, implement the IValueConverter interface. You should now have a Convert and a ConvertBack method. We are just adding two lines of code to the Convert method:

            var args = (KeyRoutedEventArgs)value;
            return args;

That’s it for the Converter. Save the class and build the project. For the next step, we need to go to our View where the Converter should do its work. Before we can use it, we need to give our Converter a key to be identified by the Binding engine. You can do this app wide in App.xaml, or in your page:

<common:KeyUpEventArgsConverter x:Key="KeyUpEventArgsConverter"/>

Also, we need to add two more references to our View (besides the Common folder that holds our converter, that is):

    xmlns:i="using:Microsoft.Xaml.Interactivity" 
    xmlns:core="using:Microsoft.Xaml.Interactions.Core"

The next step is to implement the Behavior to our input control (a TextBox in my case):

<TextBox  Header="enter search terms" PlaceholderText="search terms" Text="{Binding KnowledgeBaseSearchTerms, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
    <i:Interaction.Behaviors>
         <core:EventTriggerBehavior EventName="KeyUp">
             <core:InvokeCommandAction
                   Command="{Binding SearchTermKeyEventArgsCommand}"
                   InputConverter="{StaticResource KeyUpEventArgsConverter}">
             </core:InvokeCommandAction>
          </core:EventTriggerBehavior>
     </i:Interaction.Behaviors>
</TextBox>

With the EventTriggerBehavior, we are able to hook into the desired event of a control. We then only need to bind to a Command in our ViewModel and tell the Behaviors SDK that it should route the “KeyUp” event using our Converter.

Let’s have a final look at the command that handles the event:

        public RelayCommand<KeyRoutedEventArgs> SearchTermKeyEventArgsCommand
        {
            get
            {
                return _searchTermKeyEventArgsCommand
                    ?? (_searchTermKeyEventArgsCommand = new RelayCommand<KeyRoutedEventArgs>(
                    p =>
                    {
                        if (p.Key == Windows.System.VirtualKey.Enter)
                        {
                            //your code here
                        }
                    }));
            }
        }

As you can see, we are using a Command that is able to take a Generic (in my case it comes from the MVVM Light Toolkit, but there are several other version floating around). Because of this, we are finally getting the KeyRoutedEventArgs into our ViewModel and are able to use its data and properties.

The VirtualKey Enumeration holds a reference to a lot of (if not all) keys and works for both hardware and virtual keyboards. This makes this code safe to use in an Universal app.

As I am quite new to MVVM, I am not entirely sure if this way is the “best” way, but it works as expected with little efforts. I hope this will be useful for some of you.

Useful links that helped me on my way to find this solution:

http://blog.galasoft.ch/posts/2014/01/using-the-eventargsconverter-in-mvvm-light-and-why-is-there-no-eventtocommand-in-the-windows-8-1-version/

https://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh868246.aspx

Happy coding, everyone!

Posted by msicc in Archive, 0 comments

Dev Story Series (Part 2 of many): Getting recent posts from WordPress into your Windows Phone and Windows 8 app

Now that we have a full WordPress JSON class, we are able to download our recent posts from WordPress into our apps for Windows Phone and Windows 8. I am still not using MVVM to keep it simple (and because I have to dive into it more deeply).

The first thing we need to do is to download the JSON string for the recent posts. The Uri scheme is pretty simple: {yourblogadresshere}?json=get_recent_posts

I declared a public string in my MainPage for that, so it is very easy to use it in our app.

The second thing we are going to do is to download the JSON string into the app.

For Windows Phone I used a WebClient, as I want to keep it compatible with the Windows Phone 7 OS. I will update the App with an dedicated WP8 version later, for the moment it is working on both OS versions. Add this code to you Page_Loaded event:

                WebClient GetPostsClient = new WebClient();
                GetPostsClient.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.Now.ToString();
                GetPostsClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(GetPostsClient_DownloadStringCompleted);
                GetPostsClient.DownloadStringAsync(new Uri(RecentPostJsonUri));

We will also have to add the Handler for GetPostsClient_DownloadStringCompleted:

 void GetPostsClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            App.jsonString_result = e.Result;
        }

In Windows 8 there is no WebClient, so I used an HttpClient:

                        HttpClient getJsonStringClient = new HttpClient();
                        getJsonStringClient.DefaultRequestHeaders.IfModifiedSince = DateTime.UtcNow;
                        App.jsonString_result = await getJsonStringClient.GetStringAsync(RecentPostJsonUri);

Both the Windows Phone and the Windows 8 apps are downloading the string asynchronously, the UI is reliable all the time. You may have noticed the additional Header that I request. This way, we are able to integrate a refresh function into our app. If we leave this out, our app uses the cached string, and users will have to exit the app to refresh the list of our posts.

You will have to declare a public static string variable for the downloaded string in App.xaml.cs, that keeps the downloaded string accessible through the whole app.

Until now we have only downloaded our JSON String, which looks like this:

image

Side note: The WordPress JSON API has a dev mode. Just add “&dev=1” to your above created Uri, and you will be able to see the whole JSON string in a readable form in your browser.

Back to our topic. Off course this is not a good format for users. They want to see only the content, without all the formatting and structuring code around.

What we need to do, is to deserialize our JSON String. This is possible with Windows Phone and Windows 8 own API, but I highly recommend to use the JSON.net library. You can download and learn more about it here. To install the library, just go to Tools>Library Package Manager>Manage NuGet Packages for Solution, search for JSON.net, and install it.

After installing the package, we are able to use only one line of code to deserialize our JSON String to our data members:

var postList = JsonConvert.DeserializeObject<Posts>(App.jsonString_result);

Now we need the deserialized data to be displayed to the user. The desired control for Windows Phone is a ListBox, for Windows 8 you it is called  ListView. We need to create an ItemTemplate in XAML and bind the data we want to show to the user (Just change ListBox to ListView for Windows 8 in XAML):

<ListBox x:Name="PostListBox">
                <ListBox.ItemTemplate>
                    <DataTemplate>
				<StackPanel>
 				<Image x:Name="PostImage" 
				       Source="{Binding thumbnail}" />
                           	<TextBlock x:Name="TitleTextBlock" 
				           Text="{Binding title}" 
					   TextWrapping="Wrap" 
					   FontSize="20" />
                                <TextBlock x:Name="PublishedTextBlock" 
					   Text="{Binding date}" 
					   FontSize="12"/>
				</StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
          </ListBox>

As you can see, we have set some Bindings in the code above. This Bindings rely on the DataContract Post, as every ListBox/ListView-Item represents one Post of our postList.

[DataContract]
public class Post
    {
        [DataMember]
        public int id { get; set; }
        [DataMember]
        public string type { get; set; }
        [DataMember]
        public string slug { get; set; }
        [DataMember]
        public string url { get; set; }
        [DataMember]
        public string status { get; set; }
        [DataMember]
        public string title { get; set; }
        [DataMember]
        public string title_plain { get; set; }
        [DataMember]
        public string content { get; set; }
        [DataMember]
        public string excerpt { get; set; }
        [DataMember]
        public string date { get; set; }
        [DataMember]
        public string modified { get; set; }
        [DataMember]
        public List<Category> categories { get; set; }
        [DataMember]
        public List<object> tags { get; set; }
        [DataMember]
        public Author author { get; set; }
        [DataMember]
        public List<comment> comments { get; set; }
        [DataMember]
        public List<Attachment> attachments { get; set; }
        [DataMember]
        public int comment_count { get; set; }
        [DataMember]
        public string comment_status { get; set; }
        [DataMember]
        public string thumbnail { get; set; }
    }

Choose the fields you want to display to create your own DataTemplate to show only the data you want. Last but not least we have to tell our app that the ItemSource of our ListBox is the deserialized list, which is also done easily:

PostListBox.ItemsSource = postList.posts;

If you now hit F5 on your keyboard, the app should be built and the device/emulator should show your recent posts in a list. You don’t need to add additional code to download the images, as the image source points already to an image and will be downloaded automatically.

Pro-Tip:

The thumbnails from the our DataContract Post are looking really ugly sometimes. To get a better looking result in your ListBox/ListView, I recommend to use the attached images. To do this, you will need the following code:

          foreach (var item in postList.posts)
            {
                var postImagefromAttachement = item.attachments.FirstOrDefault();
                if (postImagefromAttachement == null)
                {
                    item.thumbnail = placeholderImage; //add your own placeholderimage here
                }
                else
                {
                    item.thumbnail = postImagefromAttachement.images.medium.url;
                }

            }

This code checks your list of attachments in your post, takes the first image, and downloads a higher quality (medium/full).  I am using medium to get best results on quality and download speed.

I hope this is helpful for some of you to get forward for to create a WordPress blog app on Windows Phone and Windows 8.

Happy coding!

Posted by msicc in Archive, 1 comment