InternetException

About coding and whatnot.

Xamarin Master-Detail Page

clock April 24, 2016 08:41 by author n.podbielski

This article as previous ones (Frame With Padding, Frame Outline Problem, Inheritance from Implicit Styles) also will be about Xamarin.
This time we will inspect Master-Detail page control/mechanism. You can find official documentation for this control here.

Quick spoiler: I never used this in any production application. Why? I will explain. Whole article will be to explain why this is just not worth your time. In this and subsequent articles I will introduce much better solution.

Xamarin MasterDetailPage control

Ok lets get to work. For a test drive lets say we have to do an application that allows user to browse stuff on some online shop. Master-Detail page will be used to allow user switch to a different category of wares. According to documentation user have to introduce only 3 files (at least) to make this work. Since I am lazy I will not create whole menu but only Master view and 3 Detail views (we cannot waste time on creating nice UI just for test right? Smile)

First main application xaml file:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:masterDetail="clr-namespace:MasterDetail;assembly=MasterDetail"
             x:Class="MasterDetail.App">
  <Application.MainPage>
    <masterDetail:MasterPage />
  </Application.MainPage>
</Application>

This cannot be more straightforward so there is no need to explain. Lets focus on MasterPage view instead:

<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:masterDetail="clr-namespace:MasterDetail;assembly=MasterDetail"
             x:Class="MasterDetail.MasterPage">
  <MasterDetailPage.Master>
    <ContentPage Title = "Test">
      <StackLayout>
        <Button Text="Detail1" />
        <Button Text="Detail2" />
        <Button Text="Detail3" />
      </StackLayout>
    </ContentPage>
  </MasterDetailPage.Master>
  <MasterDetailPage.Detail>
    <NavigationPage>
      <x:Arguments>
        <masterDetail:Detail1 />
      </x:Arguments>
    </NavigationPage>
  </MasterDetailPage.Detail>
</MasterDetailPage>

This file is a little more complicated but after few seconds it is clear that intention is to have 3 'menu' buttons that send you to different Detail pages.

Single Detail page could look like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MasterDetail.Detail1">
  <Label Text="Detail1" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

Again, nothing interesting just a label to see if correct Detail page is displayed.

Above application will start and display something similar to this:

 

Ok. I lied a little. Smile You need one more file to actually make navigation between Detail pages work. Ok lets handle this in MasterPage.xaml.cs code behind and create those details pages. For now two more files will be enough.

using System;
using Xamarin.Forms;

namespace MasterDetail
{
    public partial class MasterPage
    {
        public MasterPage()
        {
            InitializeComponent();
        }

        private void Button1_OnClicked(object sender, EventArgs e)
        {
            Detail = (new Detail1());
        }

        private void Button2_OnClicked(object sender, EventArgs e)
        {
            Detail = new NavigationPage(new Detail2());
        }

        private void Button3_OnClicked(object sender, EventArgs e)
        {
            Detail = new NavigationPage(new Detail3());
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MasterDetail.Detail3">
  <Label Text="Detail3" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MasterDetail.Detail2">
  <Label Text="Detail2" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

First: code behind that handles navigation. If you will read carefully you will notice some differences in handling detail pages. Two others are almost exactly the same as fist Detail page.

After running that solution you will see that there are really no difference between Detail1 and Detail2.

 

Why new NavigationPage() then? Because Xamarin documentation says:

The page type is wrapped in a NavigationPage instance in order to ensure that the icon referenced through the Icon property on the MasterPage is shown on the detail page in iOS.

Ok... But what if you do not write for iOS? They do not say. So you have to ensure iOS compatibility... you know just in case. Why you? Should not Xamarin take care of things like that?

Anyway, even after enclosing all of the detail pages inside a NavigationPage (even if just for having exactly the same view layout in all of them) it do not work quite well.

Why? Let us do quick experiment and press back button (if there is one on device) - it will cause application to go into background (or at least it does on Android). What is the cause of that? It works like that because there is change of NavigationPage with every Detail page and NavigationPage is object that handles... well navigation.

Luckily there is a rather easy fix for this too:

namespace MasterDetail
{
    public partial class MasterPage
    {
        public MasterPage()
        {
            InitializeComponent();
        }

        private void Button1_OnClicked(object sender, EventArgs e)
        {
            ChangeDetail(new Detail1());
        }

        private void Button2_OnClicked(object sender, EventArgs e)
        {
            ChangeDetail(new Detail2());
        }

        private void Button3_OnClicked(object sender, EventArgs e)
        {
            ChangeDetail(new Detail3());
        }

        private void ChangeDetail(Page page)
        {
            var navigationPage = Detail as NavigationPage;
            if (navigationPage != null)
            {
                navigationPage.PushAsync(page);
                return;
            }
            Detail = new NavigationPage(page);
        }
    }
}

Since there is a bit of logic involved a new method has been added - ChangeDetail. I think it is self explanatory: we just test if there is already NavigationPage and reuse that one.

This is again code that could be easily (and should be in my opinion) in Xamarin implementation of Detail property. But hey! There is Master-Detail mechanism right? If you unlucky to be unhappy with it - well you are unlucky. Xamarin Team certainly can't let you have virtual property Detail so you could do that a better way (they have rather unpleasant tendency to have everything internal/closed/sealed).

Let us continue main topic. Just for the sake of an example lets pretend that your manager, or marketing team, or anyone that is using your appm, thinks that application do not need that wide navigation menu. They think that 50 units will suffice and they ask if you can change it. You are starting maybe from setting it in StackLayout:

<StackLayout WidthRequest="50">
  <Button Text="Detail1" Clicked="Button1_OnClicked" />
  <Button Text="Detail2" Clicked="Button2_OnClicked" />
  <Button Text="Detail3" Clicked="Button3_OnClicked" />
</StackLayout>

But if does not work. Ok... Maybe this will work:

<ContentPage Title="Test" WidthRequest="50">
  <StackLayout WidthRequest="50">
    <Button Text="Detail1" Clicked="Button1_OnClicked" />
    <Button Text="Detail2" Clicked="Button2_OnClicked" />
    <Button Text="Detail3" Clicked="Button3_OnClicked" />
  </StackLayout>
</ContentPage>

No. Maybe MasterDetailPage.Master have property for this? Nope. Maybe MasterDetailPage? Nope. You can't do that. Xamarin developers did not think of that. You would have to forward the information that this change is impossible (or better easily done/would require one week of work Smile) for now.

After some time you maybe have another request, but with remark that this is absolutely necessary: menu have to go to the right edge.

You can check if MasterBehaviour property have something that can help you with that and according to documentation its enumeration type have following values:

  • Default – The pages are displayed using the platform default.
  • Popover – The detail page covers, or partially covers the master page.
  • Split – The master page is displayed on the left and the detail page is on the right.
  • SplitOnLandscape – A split screen is used when the device is in landscape orientation.
  • SplitOnPortrait – A split screen is used when the device is in portrait orientation.

As you see it does not anything helpful. Since there are only four other properties in this control you loose hope and explains to anyone requesting this change that it will need 2 weeks of works since you have to research new solution, implement and test it. At least.

Maybe I am pessimist but there are always changes and they in 90% about adding new features/code instead of removing so it is much more probable that you will have to change how Master and Detail mechanism work because of new requirement/device/theme etc.

Of course you can modify presentation by creating new renderer but it is really complex class and would only solve issues in one platform. No. This is not recommended solution. 

All those missing features and inability to configure anything is just only part of the problem. How many times you are writing application with Xaml files that uses only views without any view models? I personnally can't think of one. Even the smallest applications are written with few views and view models for them. Even models and database for small application are not that rare.

Lets think about above example. You have menu handlers in .xaml.cs file. I almost never use those and instead of them I use commands. Can you use them here? Not really, because you don't have access to Detail property in different object. You would have to create static property or method at least to allow yourself have access to property that is pretty much whole point of this control.
But static property can not be used in tests (at least easily) so better is to create special interface and have public access to its implementation somewhere. IoC container maybe? If you use this pattern you probably have IoC constructors in some classes, most probably in view models and those can't be created easily in view click handlers, like in above example, or in ListView.ItemSelected handler like Xamarin documentation suggests.

Best thing is to use commands and some interface in my opinion. This would be easiest thing to do to amend that discrepancy. But lets think of it from other angle.

I am big fan of separating classes in smaller parts for readability, easier maintenance, testability etc. The same thing can in my opinion can be said (to some extent) about xaml files. Can this be done in MasterPage.xaml file? For example you will decide to extract from there Master page and put it in Menu.xaml. Can you do that? Not easily because you can not move ButtonX_OnClicked handlers easily because they depend of MasterDetailPage.Detail property. Of course you can create interface the same as with view model problem, but again it shows that MasterDetailPage control creates more problems then it solves.

After reading about this control I decided not to use it because all of things covered above. In fact in my opinion this control is pretty much useless, But what to use instead?

ContentTemplate and ContentPresenter

First idea is to use newly added features of templating mechanism by ContentTemplate and ContentPresenter.

Let us add new button to MasterPage.xaml file:

<Button Text="Detail4" Clicked="Button4_OnClicked" />

To create ContentTemplate we have to add just one item to resources in our application, preferably in App.xaml:

<Application.Resources>
  <ResourceDictionary>
    <ControlTemplate x:Key="DetailTemplate">
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition Width="250"></ColumnDefinition>
          <ColumnDefinition Width="*"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <StackLayout BackgroundColor="Red">
          <Button Text="Detail1"></Button>
          <Button Text="Detail2"></Button>
          <Button Text="Detail3"></Button>
        </StackLayout>
        <ContentPresenter Grid.Column="1">
            
        </ContentPresenter>
      </Grid>
    </ControlTemplate>
  </ResourceDictionary>
</Application.Resources>

There is only 3 buttons just to show that it is different view. Red background is for the same thing. There is no handling of buttons because of the problems with MasterDetailPage control explained above. It is just a demo for templating mechanism.

Creating forth detail page called Detail4 like this:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MasterDetail.Detail4"
             ControlTemplate="{StaticResource DetailTemplate}">
  <Label Text="Detail4" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

is enough for now.

Last thing is to handle button click MasterPage.xaml.cs:

private void Button4_OnClicked(object sender, EventArgs e)
{
    App.Current.MainPage = new Detail4();
}

Yes this is also handled in xaml code behind file, but since this uses static App.Current property it can be easily moved to view model command property.

After running and trying out new button we will see something like this.

 

We have 250 width, red background. We can edit this view in every way possible for any page. We will do not have any problems with previous example change requests.

But there is other problem. What if we will have use state somehow in a way of coloring or disabling current page button? It is not that easy. Since it is a template and not separate control we can't have different BindingContext for menu and Detail page. The same view model for both sooner or later will cause some problems and it will not be most obvious one, using the same view model for all or maybe different ones but with the same values for menu?

More complex problems will be caused by complexity of menu. If you will have to i.e. 2-level menu and collapse, expand sub menus user will almost sure will see that every time after opening new detail page.

This mechanism is more usable for theming application, reusing some external library control with styles for every application etc.

If not templates then what?

Custom MasterDetail control

Yes. If you want job done well, do it your self.

First of all, requirements:

1. Control should have default view model.

2. Changing detail pages must be handled from view models.

3. Control should be created once.

4. Control should handle back button.

5. View should be allowed to override when neccessary.

 

Seems easy, right? Smile

Lets start with creating App.xamlfile and its code behind file:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomMasterDetail.App">
</Application>
namespace CustomMasterDetail
{
    public partial class App
    {
        public App()
        {
            InitializeComponent();
            MainPage = new MasterDetail();
        }
    }
}

Simple right? To make this correct we have to also create this MasterDetail class. But since view model is required, let us start there:

using System.ComponentModel;
using System.Runtime.CompilerServices;
 
namespace CustomMasterDetail.ViewModel
{
    public class MasterDetailViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

For now this can be any view model – it is just a minimal base implementation. We need to add Detail property:

private View _detail;
public View Detail
{
    get { return _detail; }
    set
    {
        _detail = value;
        OnPropertyChanged();
    }
}

If you wondering about OnPropertyChange call, yes it will be binded. It is not clearest implementation of View-ViewModel pattern but it is clear and simple and it will be enough for now.

Ok. Lets jump to view. We will start with simple xaml page:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomMasterDetail.MasterDetail">
</ContentPage>

There are two things missing:

  1. Menu
  2. Detail page presentation

To add them we need to create xaml definition for first and BindableProperty for second one. We will start with second one.

public readonly BindableProperty DetailProperty = BindableProperty.Create("Detail",typeof(ContentPage));
 
public ContentPage Detail
{
    get { return (ContentPage)GetValue(DetailProperty); }
    set { SetValue(DetailProperty, value); }
}

There is one thing that might be confusing. Detail property type is a ContentPage because of example simplicity. It could be also View because this is base type of any control that could be root of detail page layout (Grid, StackLayout etc.). Page would be also doable but it would require some magic to obtain root view from i.e. CarouselPage and still allow user to use its navigation features.

We will get back to this topic.

Menu will be the same as in previous examples.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="250" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <StackLayout Grid.Column="0">
        <Button Text="Detail1" />
        <Button Text="Detail2" />
        <Button Text="Detail3" />
    </StackLayout>
</Grid>

Grid control allows us to add menu and detail page and controls how they are connected in very simple but yet powerful way.

We need to connect Detail properties of control and view model and we can do that with simple binding:

public MasterDetail()
{
    InitializeComponent();
    SetBinding(DetailProperty, new Binding("Detail", BindingMode.OneWay));
}

We need to do this in a code behind and not in xaml because xaml operate in base class context and we need this in our class. Yes we could do this in other xaml file (in this case in App.xaml) but then we had to do this every single time we would use this control, which would really defeat whole purpose of creating separate control

Now we can define where Detail page will be in our layout and it will be second column of Grid. Of course this can any other place in Master page – top, right, bottom. You can even create multiple parts of master page that are permanently visible, in every detail page. Doing this way you can create i.e. extra properties in master view model and in detail view models that allows you hide, show this other parts, change displayed text, add buttons and etc. This is why it is better to do it this way instead of using Xamarin poor control.

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="250" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <StackLayout Grid.Column="0">
        <Button Text="Detail1" />
        <Button Text="Detail2" />
        <Button Text="Detail3" />
    </StackLayout>
    <ContentView Grid.Column="1" x:Name="DetailContainer" />
</Grid>

Change of view model property. triggers change of View property. which is handled in BindableProperty definition via propertyChanged parameter:

public readonly BindableProperty DetailProperty = BindableProperty.Create("Detail",
    typeof(ContentPage), typeof(MasterDetailControl),
    propertyChanged: (bindable, value, newValue) =>
    {
        var masterPage = (MasterDetailControl)bindable;
        View content;
        var contentPage = (ContentPage)newValue;
        if (contentPage != null)
        {
            content = contentPage.Content;
            content.BindingContext = contentPage.BindingContext;
        }
        else content = null;
        masterPage.DetailContainer.Content = content;
        masterPage.OnPropertyChanged("SideContentVisible");
    });

Now it is much clearer why there is ContentPage type used for Detail properties in view and view model –  this type have Content property, which is set as Content of our newly added ContentView control named DetailContainer. It is important to mark why there is assignment of content BindingContext property - without it this value (in masterPage.DetailContainer.Content) would be resolved to parent value, which would be MasterDetailControl.BindingContext. We do not want that. Instead there is assigned directly detail view model to it, which is what is expected when you edit detail page xaml - it suppose to be this page view model.

Ok. As you can see we have easily configurable layout of control, Detail page easily accessible from ViewModel. However we do not have required support for INavigation interface right?

Let’s take care of it now. Easiest way will be to add this interface to view model:

public MasterDetailViewModel(INavigation navigation)
{
     _navigation = navigation;
}

private Stack _pages = new Stack();

public void InsertPageBefore(Page page, Page before)
{
    if (_pages.Contains(before))
    {
        var list = _pages.ToList();
        var indexOfBefore = list.IndexOf(before);
        list.Insert(indexOfBefore, page);
        _pages = new Stack(list);
    }
    else
    {
        _navigation.InsertPageBefore(page, before);
    }
}

public Task PopAsync()
{
    Page page = null;
    if (_pages.Count > 0)
    {
        page = _pages.Pop();
        _detail = page;
        OnPropertyChanged("Detail");
    }
    return page != null ? Task.FromResult(page) : _navigation.PopAsync();
}

public Task PopAsync(bool animated)
{
    Page page = null;
    if (_pages.Count > 0)
    {
        page = _pages.Pop();
        _detail = page;
        OnPropertyChanged("Detail");
    }
    return page != null ? Task.FromResult(page) : _navigation.PopAsync(animated);
}

public Task PopModalAsync()
{
    return _navigation.PopModalAsync();
}

public Task PopModalAsync(bool animated)
{
    return _navigation.PopModalAsync(animated);
}

public Task PopToRootAsync()
{
    var firstPage = _navigation.NavigationStack[0];
    if (firstPage is MasterDetail
        || firstPage.GetType() == typeof(MasterDetail))
    {
        _pages = new Stack(new[] { _pages.FirstOrDefault() });
        return Task.FromResult(firstPage);
    }
    return _navigation.PopToRootAsync();
}

public Task PopToRootAsync(bool animated)
{

    var firstPage = _navigation.NavigationStack[0];
    if (firstPage is MasterDetail
        || firstPage.GetType() == typeof(MasterDetail))
    {
        _pages = new Stack(new[] { _pages.FirstOrDefault() });
        return Task.FromResult(firstPage);
    }
    return _navigation.PopToRootAsync(animated);
}

public Task PushAsync(Page page)
{
    Detail = page;
    return Task.FromResult(page);
}

public Task PushAsync(Page page, bool animated)
{
    Detail = page;
    return Task.FromResult(page);
}

public Task PushModalAsync(Page page)
{
    return _navigation.PushModalAsync(page);
}

public Task PushModalAsync(Page page, bool animated)
{
    return _navigation.PushModalAsync(page, animated);
}

public void RemovePage(Page page)
{
    if (_pages.Contains(page))
    {
        var list = _pages.ToList();
        list.Remove(page);
        _pages = new Stack(list);
    }
    _navigation.RemovePage(page);
}

public IReadOnlyList ModalStack { get { return _navigation.ModalStack; } }

public IReadOnlyList NavigationStack
{
    get
    {
        if (_pages.Count == 0)
        {
            return _navigation.NavigationStack;
        }
        var implPages = _navigation.NavigationStack;
        MasterDetail master = null;
        var beforeMaster = implPages.TakeWhile(d =>
        {
            master = d as MasterDetail;
            return d is MasterDetail || d.GetType() == typeof(MasterDetail);
        }).ToList();
        beforeMaster.AddRange(_pages);
        beforeMaster.AddRange(implPages.Where(d => !beforeMaster.Contains(d)
            && d != master));
        return new ReadOnlyCollection(_navigation.NavigationStack.ToList());
    }
}

It may look a little complicated but most important are only 2 methods, PushAsync and PopAsync for navigation inside an application. Modal windows functionality is just redirected to Xamarin implementation of interface. ModalStack and NavigationStack properties may be usable sometimes. First just unifies Xamarin stack and MasterPage stack (from _pages field) into one. Rest of interface is not really helpfull in most of applications, but it is implemented as ax example even if would be possible to implement only PopAsync and PushAsync methods or even creating simpler interface only for navigation inside MasterPage.

With that kind of implementation of INavigation interface we can use it inside of OnBackButtonPressed override in MasterPage:

protected override bool OnBackButtonPressed()
{
    var viewModel = BindingContext as MasterDetailViewModel;
    if (viewModel != null)
    {
        var navigation = (INavigation)viewModel;
        navigation.PopAsync();
        return true;
    }
    return base.OnBackButtonPressed();
}

Above code fulfils our requirements. MasterDetail.xaml is easy to change and it is created only once. MasterDetailViewModel is specific view model for control and its INavigation implementation makes detail page navigation easily available from outside of control. The same interface allows handling of backbutton in control.

Next thing to do: it would be nice to have MasterDetail control in reusable portable library.

MasterDetailControl in PCL library

Placing our new control in separate PCL (Portable Class Library), allow to reuse it in multiple applications. It is very useful if you have multiple applications with similar themes. Then it is possible to place whole theme in single PCL.

Lets start with creating PCL project i.e. named CustomMasterDetailControl. We need to add xaml file and view model class to this project. Most of that code will be copied from previous example.

First, xaml file MasterDetailControl.

<?xml version="1.0" encoding="utf-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                x:Class="CustomMasterDetailControl.MasterDetailControl">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <StackLayout Grid.Column="0" x:Name="SideContentContainer" />
        <ContentView Grid.Column="1" x:Name="DetailContainer" />
    </Grid>
</ContentPage>

There is one change from previous version. Instead of having menu in StackLayout control we just assigning name to this control so now it is available in code behind.

public partial class MasterDetailControl
{
    public static readonly BindableProperty SideContentProperty = BindableProperty.Create("SideContent",
        typeof(View), typeof(MasterDetailControl), null, propertyChanged: (bindable, value, newValue) =>
        {
            var control = (MasterDetailControl)bindable;
            control.SideContentContainer.Children.Clear();
            control.SideContentContainer.Children.Add(control.SideContent);
        });

    public readonly BindableProperty DetailProperty = BindableProperty.Create("Detail",
    typeof(ContentPage), typeof(MasterDetailControl),
    propertyChanged: (bindable, value, newValue) =>
    {
        var masterPage = (MasterDetailControl)bindable;
        masterPage.DetailContainer.Content = newValue != null ?
            ((ContentPage)newValue).Content : null;
    });

    public MasterDetailControl()
    {
        InitializeComponent();
        SetBinding(DetailProperty, new Binding("Detail", BindingMode.OneWay));
    }

    public ContentPage Detail
    {
        get { return (ContentPage)GetValue(DetailProperty); }
        set { SetValue(DetailProperty, value); }
    }

    public View SideContent
    {
        get { return (View)GetValue(SideContentProperty); }
        set { SetValue(SideContentProperty, value); }
    }

    public static Page Create<TView, TViewModel>() where TView : MasterDetailControl, new()
        where TViewModel : MasterDetailControlViewModel, new()
    {
        var masterDetail = new TView();
        var navigationPage = new NavigationPage(masterDetail);
        var viewModel = new TViewModel();
        viewModel.SetNavigation(navigationPage.Navigation);
        masterDetail.BindingContext = viewModel;
        return navigationPage;
    }

    protected override bool OnBackButtonPressed()
    {
        var viewModel = BindingContext as MasterDetailControlViewModel;
        if (viewModel != null)
        {
            var navigation = (INavigation)viewModel;
            navigation.PopAsync();
            return true;
        }
        return base.OnBackButtonPressed();
    }
}

With Bindable property defined like this we can override side content of MasterDetailControl in our every application like this:

<MasterDetailControl.SideContent>
    <StackLayout>
        <Button Text="Detail1" Command="{Binding ToDetail1}" />
        <Button Text="Detail2" Command="{Binding ToDetail2}" />
        <Button Text="Detail3" Command="{Binding ToDetail3}" />
    </StackLayout>
</MasterDetailControl.SideContent>

Very easy and intuitive.

There is also new method that should be used to create instance of our control and override view model type for it:

public static Page Create<TView, TViewModel>() where TView : MasterDetailControl, new()
    where TViewModel : MasterDetailControlViewModel, new()
{
    var masterDetail = new TView();
    var navigationPage = new NavigationPage(masterDetail);
    var viewModel = new TViewModel();
    viewModel.SetNavigation(navigationPage.Navigation);
    masterDetail.BindingContext = viewModel;
    return navigationPage;
}

This method contains logic that was previously in App.xaml.cs file:

public App()
{
    InitializeComponent();
    var masterDetail = new MasterDetail();
    var navigationPage = new NavigationPage(masterDetail);
    MainPage = navigationPage;
    masterDetail.BindingContext = new MasterDetailViewModel(navigationPage.Navigation);
}

However there is no point in forcing this code in every application. Instead we can use new method in following way:

public App()
{
    InitializeComponent();
    MainPage = MasterDetailControl.Create<MasterDetail, MasterDetailViewModel>();
}

Best way to set MainPage of application in my opinion would be to set it in xaml file of App class, but this would force as to i.e. rewrite our control so it would derive from NavigationPage instead and then add the same Bindable properties to this new type to propagate those values to our actual control. I do not think that getting rid one line in code justifies that kind of complexity.

Of course if MasterDetailViewModel class do not have parameterless constructor (because of IoC i.e.) we can create new method that takes instance of view model type and change previous overload a little:

public static Page Create<TView, TViewModel>() where TView : MasterDetailControl, new()
    where TViewModel : MasterDetailControlViewModel, new()
{
    return Create<TView, TViewModel>(new TViewModel());
}

public static Page Create<TView, TViewModel>(TViewModel viewModel) where TView : MasterDetailControl, new()    
    where TViewModel : MasterDetailControlViewModel
{
    var masterDetail = new TView();
    var navigationPage = new NavigationPage(masterDetail);
    viewModel.SetNavigation(navigationPage.Navigation);
    masterDetail.BindingContext = viewModel;
    return navigationPage;
}

Now lets focus on base class for new control view model: MasterDetailControlViewModel. It is almost the same as in previous example, but it do not contain any logic that handles side menu functionality.

public class MasterDetailControlViewModel : INotifyPropertyChanged, INavigation
{
    private Page _detail;
    private INavigation _navigation;

    private Stack<Page> _pages = new Stack<Page>();

    public event PropertyChangedEventHandler PropertyChanged;

    public Page Detail
    {
        get { return _detail; }
        set
        {
            if (_detail != value)
            {
                _pages.Push(Detail);
                _detail = value;
                OnPropertyChanged();
            }
        }
    }

    public IReadOnlyList<Page> ModalStack { get { return _navigation.ModalStack; } }

    public IReadOnlyList<Page> NavigationStack
    {
        get
        {
            if (_pages.Count == 0)
            {
                return _navigation.NavigationStack;
            }
            var implPages = _navigation.NavigationStack;
            MasterDetailControl master = null;
            var beforeMaster = implPages.TakeWhile(d =>
            {
                master = d as MasterDetailControl;
                return master != null || d.GetType() == typeof(MasterDetailControl);
            }).ToList();
            beforeMaster.AddRange(_pages);
            beforeMaster.AddRange(implPages.Where(d => !beforeMaster.Contains(d)
                && d != master));
            return new ReadOnlyCollection<Page>(_navigation.NavigationStack.ToList());
        }
    }

    public void InsertPageBefore(Page page, Page before)
    {
        if (_pages.Contains(before))
        {
            var list = _pages.ToList();
            var indexOfBefore = list.IndexOf(before);
            list.Insert(indexOfBefore, page);
            _pages = new Stack<Page>(list);
        }
        else
        {
            _navigation.InsertPageBefore(page, before);
        }
    }

    public Task<Page> PopAsync()
    {
        Page page = null;
        if (_pages.Count > 0)
        {
            page = _pages.Pop();
            _detail = page;
            OnPropertyChanged("Detail");
        }
        return page != null ? Task.FromResult(page) : _navigation.PopAsync();
    }

    public Task<Page> PopAsync(bool animated)
    {
        Page page = null;
        if (_pages.Count > 0)
        {
            page = _pages.Pop();
            _detail = page;
            OnPropertyChanged("Detail");
        }
        return page != null ? Task.FromResult(page) : _navigation.PopAsync(animated);
    }

    public Task<Page> PopModalAsync()
    {
        return _navigation.PopModalAsync();
    }

    public Task<Page> PopModalAsync(bool animated)
    {
        return _navigation.PopModalAsync(animated);
    }

    public Task PopToRootAsync()
    {
        var firstPage = _navigation.NavigationStack[0];
        if (firstPage is MasterDetailControl
            || firstPage.GetType() == typeof(MasterDetailControl))
        {
            _pages = new Stack<Page>(new[] { _pages.FirstOrDefault() });
            return Task.FromResult(firstPage);
        }
        return _navigation.PopToRootAsync();
    }

    public Task PopToRootAsync(bool animated)
    {
        var firstPage = _navigation.NavigationStack[0];
        if (firstPage is MasterDetailControl
            || firstPage.GetType() == typeof(MasterDetailControl))
        {
            _pages = new Stack<Page>(new[] { _pages.FirstOrDefault() });
            return Task.FromResult(firstPage);
        }
        return _navigation.PopToRootAsync(animated);
    }

    public Task PushAsync(Page page)
    {
        Detail = page;
        return Task.FromResult(page);
    }

    public Task PushAsync(Page page, bool animated)
    {
        Detail = page;
        return Task.FromResult(page);
    }

    public Task PushModalAsync(Page page)
    {
        return _navigation.PushModalAsync(page);
    }

    public Task PushModalAsync(Page page, bool animated)
    {
        return _navigation.PushModalAsync(page, animated);
    }

    public void RemovePage(Page page)
    {
        if (_pages.Contains(page))
        {
            var list = _pages.ToList();
            list.Remove(page);
            _pages = new Stack<Page>(list);
        }
        _navigation.RemovePage(page);
    }

    public void SetNavigation(INavigation navigation)
    {
        _navigation = navigation;
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Anything that will involve siide menu will be in application specific code view model. Application will contains from the same detail views.

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomMasterDetail2.DetailX">
  <Label Text="DetailX" VerticalOptions="Center" HorizontalOptions="Center" />
</ContentPage>

App.xaml file is also the same and most of its code behind was shown above.

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomMasterDetail2.App">
</Application>
using CustomMasterDetailControl;

namespace CustomMasterDetail2
{
    public partial class App
    {
        public App()
        {
            InitializeComponent();
            MainPage = MasterDetailControl.Create<MasterDetail, MasterDetailViewModel>();
        }
    }
}

MasterDetail.xaml file is application specific implementation of control and contains menu (the same as in previous example).

<?xml version="1.0" encoding="utf-8" ?>
<masterDetail:MasterDetailControl 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:masterDetail="clr-namespace:CustomMasterDetailControl;assembly=CustomMasterDetailControl"
    x:Class="CustomMasterDetail2.MasterDetail">
    <masterDetail:MasterDetailControl.SideContent>
        <StackLayout>
            <Button Text="Detail1" Command="{Binding ToDetail1}" />
            <Button Text="Detail2" Command="{Binding ToDetail2}" />
            <Button Text="Detail3" Command="{Binding ToDetail3}" />
        </StackLayout>
    </masterDetail:MasterDetailControl.SideContent>
</masterDetail:MasterDetailControl>

Menu logic is of course contained in view model, MasterDetailViewModel class.

public class MasterDetailViewModel : MasterDetailControlViewModel
{
    private ICommand _toDetail1;
    private ICommand _toDetail2;
    private ICommand _toDetail3;

    public ICommand ToDetail1
    {
        get
        {
            return _toDetail1 ?? (_toDetail1 = new Command(OnToDetail1));
        }
    }

    public ICommand ToDetail2
    {
        get
        {
            return _toDetail2 ?? (_toDetail2 = new Command(OnToDetail2));
        }
    }

    public ICommand ToDetail3
    {
        get
        {
            return _toDetail3 ?? (_toDetail3 = new Command(OnToDetail3));
        }
    }

    private void OnToDetail1()
    {
        Detail = new Detail1();
    }

    private void OnToDetail2()
    {
        Detail = new Detail2();
    }

    private void OnToDetail3()
    {
        Detail = new Detail3();
    }
}

After running this application effect will be the same as in previous one.

 

Best thing about this solution is great possibilities of configuration. In MasterDetailControl.xaml you can change anything you want: layout, widths, heights of elements, adds new bars on top or bottom, etc.

For example if we would want to hide menu on some detail pages, we can add new property to our control:

public bool SideContentVisible
{
    get { return Detail.SideContentVisible; }
}

Obviously for this to work there is need for above property SideContentVisible in detail page. Since our details are just ContentPage class instances we need to create new base class for details. Best way is to put it in PCL library along to our MasterDetailControl class.

public class DetailPage : ContentPage
{
    public DetailPage()
    {
        SideContentVisible = true;
    }

    public bool SideContentVisible { get; set; }
}

Obviously we need to change base classes of all details for this work. It is sometimes unnecessary or not desired, so let's change property in master detail control instead.

public bool IsMenuVisible
{
    get
    {
        var detailPage = Detail as DetailPage;
        if (detailPage != null)
        {
            return detailPage.SideContentVisible;
        }
        return true;
    }
}

This will handle ContentPage details to - menu visibility will just default to true. We can now create new detail called i.e. NoMenuDetail.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<masterDetail:DetailPage xmlns="http://xamarin.com/schemas/2014/forms"
                         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                         xmlns:masterDetail="clr-namespace:CustomMasterDetailControl;assembly=CustomMasterDetailControl"
                         x:Class="CustomMasterDetail2.NoMenuDetail"
                         SideContentVisible="False">
  <Label Text="No menu detail page" VerticalOptions="Center" HorizontalOptions="Center" />
</masterDetail:DetailPage>

We need only to add new menu item to application MasterDetail.xaml and handle this item command in view model.

<Button Text="NoMenuDetail" Command="{Binding ToNoMenuDetail}" />
private ICommand _toNoMenuDetail;

public ICommand ToNoMenuDetail
{
    get
    {
        return _toNoMenuDetail ?? (_toNoMenuDetail = new Command(OnToNoMenuDetail));
    }
}

private void OnToNoMenuDetail()
{
    Detail = new NoMenuDetail();
}

We need, of course, to create appropriate binding for this in MasterDetailControl.xaml and notify about property change, everytime Detail property changes.

<?xml version="1.0" encoding="utf-8"?>

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="CustomMasterDetailControl.MasterDetailControl"
             x:Name="Parent">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <StackLayout Grid.Column="0" x:Name="SideContentContainer"
                 WidthRequest="250"
                 IsVisible="{Binding SideContentVisible, Source={x:Reference Name=Parent}}" />
    <ContentView Grid.Column="1" x:Name="DetailContainer" />
  </Grid>
</ContentPage>

Binding is done by referencing control by its xaml name "Parent", which allows us to use it for binding source. It is impossible any other way in Xamaring without custom IMarkupExtension implementation (but I strongly encourage you to do that Smile). Another thing, that is worth to explain, is Auto width of side content Grid column. Without that change this column would take space even if its content would be invisible. Width of 250 is moved to WidthRequest property of StackLayout that serve as a container for menu.

Notification about SideContentVisible property change should be done every time detail changes and it involves only one line in DetailProperty declaration.

public readonly BindableProperty DetailProperty = BindableProperty.Create("Detail",
    typeof(ContentPage), typeof(MasterDetailControl),
    propertyChanged: (bindable, value, newValue) =>
    {
        var masterPage = (MasterDetailControl)bindable;
        masterPage.DetailContainer.Content = newValue != null ?
            ((ContentPage)newValue).Content : null;
        masterPage.OnPropertyChanged("SideContentVisible");
    });

After running changed code we will see on mobile device screen something like this:

 

After clicking on new menu item menu will disapper:

 

Summary

Above examples can serve as a base to create more specific controls thanks to great flexibility of this solution. It is defined by developer and it is tottally open in contrast to Xamarin native solution with it internal functionality, not accesible to end user of Xamarin. Since navigation really happens in view model it is much more viable for bigger applications that in most cases do not have parameterless constructors for view models and other classes. Base classes for control and its view model handles basic functionality, which can be extened very easily, so there is no need to do it every time in every single application. Control is created only once, which helps conserve memory. This would be impossible if every single page had the same menu. Oh, and it handles back button well Smile.

Sample applications with code examples used in this article you can find here: XamarinSamples.zip (94.48 kb)

Also there is available public github repository with code for this article and previous ones from Xamarin series.

Some features might still be missing or few things might be handled better. For example navigation from view model could be done by creating view models instead of views. This is better pattern and it is much simpler since navigation requires creating only one instance of view model instead of view and view model (at least in final application logic code). This would need some mechanism for finding out proper view for view model and/or registration mechanism for those pairs. Also it would be much easier to have the same navigation for detail pages and simple, whole screen content pages. For this detail pages can identified by base class DetailPage. This would create nice and simple navigation for every page via just view models regardless of specifics of a layout of views (which should not be connected to application logic anyway).

I will cover those topics in next article.

 



Xamarin Style based on implicit Style

clock April 23, 2016 00:17 by author n.podbielski

Next article about bugs in Xamarin will touch topic of Styles. Styles for all of controls not only Frame (and if you wondering why Frame you should check first two articles about Xamarin here and here).
First of all if you are using Styles in Xamarin you probably know how to define implicit styles. If not here is a sample:

<Application.Resources>
  <ResourceDictionary>
    <Style TargetType="Label">
      <Setter Property="FontSize" Value="45" />
    </Style>
  </ResourceDictionary>
</Application.Resources>

Almost the same as in WPF. If you will, or already did, use those kind of styles extensively you probably encountered problem with inheritance from them. How to do it? First consider this xaml:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="StylesInheritance.App">
  <Application.Resources>
    <ResourceDictionary>
      <Style TargetType="Label">
        <Setter Property="FontSize" Value="45" />
      </Style>
    </ResourceDictionary>
  </Application.Resources>
  <Application.MainPage>
    <ContentPage>
      <Grid>
        <Grid.Resources>
          <ResourceDictionary>
            <Style TargetType="Label">
              <Setter Property="BackgroundColor" Value="Red"></Setter>
            </Style>
          </ResourceDictionary>
        </Grid.Resources>
        <Label Text="Label Text" />
      </Grid>
    </ContentPage>
  </Application.MainPage>
</Application>

You have global implicit style for Label and want, locally for Grid, add red background too. According to this Xamarin documentation it should be possible right? Style have BaseResourceKey property, which won't be helpful since implicit styles do not have keys (actually they do but we will get back to this), but there is also property BasedOn. If you have Resharper you can even taste how this should work with Intellisense:

Should work, but it do not. Ok. Resharper inserts what it looks like a correct Xaml:

<Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
  <Setter Property="BackgroundColor" Value="Red"></Setter>
</Style>

 But after application starts we have (un)welcoming error:

 

Why this resource is not found? It is there, right? Notice strange key value, we will get back to that.

Maybe you will (or already did tried) to use Key property of StaticResourceExtension?

<Style TargetType="Label" BasedOn="{StaticResource Key={x:Type Label}}">
  <Setter Property="BackgroundColor" Value="Red"></Setter>
</Style>

You will see another error:

 

That was something to be expected really since Key property is a string.

If you are so distrustful as me, maybe you tried to actually inspect Application resources to check if they are really there:

 

Implicit style is there oh right. Why Framework cannot find something that put in there itself? If you are perceptive you probably noticed that Keys is collection of strings and implicit styles actually do have keys, which are FullName of target types. We will have to do figure out how to set appropriate key for this type of styles. The easiest way is:

<Style TargetType="Label" BasedOn="{StaticResource Xamarin.Forms.Label}">
  <Setter Property="BackgroundColor" Value="Red"></Setter>
</Style>

<Style TargetType="Label" BasedOn="{StaticResource Key=Xamarin.Forms.Label}">
  <Setter Property="BackgroundColor" Value="Red"></Setter>
</Style>

The problem with first solution is that Resharper marks it as invalid (yeah this is really weak problem, but I like to my code to be clean that way) and second is not even checked for validity - you can put there anything - so it is even worse since you have only runtime errors. Of cource you can also assign proper key to implicit styles and make them explicit, and then assign this key to all controls, and then assign this key to child styles, and... well... this is to much work Wink.

On the side, I really do not get why Xamarin Team decided to make Resources keys a string and not objects like in WPF. If this would be the case, second Style declaration would work just fine.

{StaticResource Key={x:Type Label}}

In my opinion this is first bug/improvement they should make.

For fixing this issue I decided to write my own StaticResourceExtension, that will correctly calculate resources keys. Unfortunately as almost everything that could be useful to override in Xamarin is sealed (see Binding i.e.; not sealed in WPF). Because of that we have to do this this way:

[ContentProperty("KeyOrType")]
public class StaticResourceExtExtension : IMarkupExtension
{
    private readonly StaticResourceExtension _xamarinStaticExtension;

    public StaticResourceExtExtension()
    {
        _xamarinStaticExtension = new StaticResourceExtension();
    }

    public object KeyOrType { get; set; }

    public object ProvideValue(IServiceProvider serviceProvider)
    {
        var type = KeyOrType as Type;
        if (type != null)
        {
            _xamarinStaticExtension.Key = type.FullName;
        }
        else
        {
            var s = KeyOrType as string;
            if (s != null)
            {
                _xamarinStaticExtension.Key = s;
            }
        }
        return _xamarinStaticExtension.ProvideValue(serviceProvider);
    }
}

This will work only in newer versions of Xamarin. For example in 1.3.3.6323 this class is internal (which is interesting how it is available in Xaml). In earlier versions you have resolve to reflection or write your own mechanism for obtaining correct resources (it is not really that complicated).

With this you declare your style like this:

<Style TargetType="Label" BasedOn="{stylesInheritance:StaticResourceExt {x:Type Label}}">
  <Setter Property="BackgroundColor" Value="Red"></Setter>
</Style>

Which will still throw and error Undecided, which is strange to me and it is second bug involving styles inheritance.

 

It is the same error as in the first try with Xamarin StaticResourceExtension. If you will debug this code you can check for KeyOrType property value:

This is the point when I just stopped amazed what I found. Laughing

Really, I expected a bug, but not like this one. If you will look closely on first screen with error, you will notice that the same thing happens in Xamarin extension (and why I think that using Xamarin is like run through minefield). Apparently Xaml parser do not expect here another extension and it threats everything as plain string instead of evaluating it and then putting it in StaticResourceExtension. However this is only one thing. Why there is no closing bracket '}'? Maybe first problem originates from second one and parser threats unclosed brackets as just string and not correctly as Xaml declaration. If we add explicitly KeyOrType property to declaration it will be resolved by parser just right.

<Style TargetType="Label" BasedOn="{stylesInheritance:StaticResourceExt KeyOrType={x:Type Label}}">
  <Setter Property="BackgroundColor" Value="Red"></Setter>
</Style>

But we did not got so far without doing it (almost) perfect! Good thing we can change how our extension behaves, in contrast to Xamarin one. We have only to resolve type from its xaml abbreviation. Luckily IServiceProvider have access for type just for that: IXamlTypeResolver. With method of this type:

Type Resolve(string qualifiedTypeName, IServiceProvider serviceProvider = null);

we can easily obain correct type.

public object ProvideValue(IServiceProvider serviceProvider)
{
    var type = KeyOrType as Type;
    if (type != null)
    {
        _xamarinStaticExtension.Key = type.FullName;
    }
    else
    {
        var s = KeyOrType as string;
        if (s != null)
        {
            const string xType = "{x:Type ";
            if (s.StartsWith(xType))
            {
                var typeName = s.Replace(xType, "");
                var xamlTypeResolver = (IXamlTypeResolver)serviceProvider.GetService(typeof(IXamlTypeResolver));
                _xamarinStaticExtension.Key = xamlTypeResolver.Resolve(typeName, serviceProvider).FullName;
            }
            else
            {
                _xamarinStaticExtension.Key = s;
            }
        }
    }
    return _xamarinStaticExtension.ProvideValue(serviceProvider);
}

And it will work. As we wanted we will see big font label on red background.

 

Of course instead of removing "{x:Type " part of string it is possible to do this:

public object ProvideValue(IServiceProvider serviceProvider)
{
    var type = KeyOrType as Type;
    if (type != null)
    {
        _xamarinStaticExtension.Key = type.FullName;
    }
    else
    {
        var s = KeyOrType as string;
        if (s != null)
        {
            const string bracket = "{";
            if (s.StartsWith(bracket))
            {
                var xamlTypeResolver = (IXamlTypeResolver)serviceProvider.GetService(typeof(IXamlTypeResolver));
                var extensionName = s.Replace(bracket, "").Split(' ')[0];
                var extension = (TypeExtension)Activator.CreateInstance(xamlTypeResolver.Resolve(extensionName, serviceProvider));
                extension.TypeName = s.Split(' ')[1];
                var typeName = extension.ProvideValue(serviceProvider).FullName;
                _xamarinStaticExtension.Key = typeName;
            }
            else
            {
                _xamarinStaticExtension.Key = s;
            }
        }
    }
    return _xamarinStaticExtension.ProvideValue(serviceProvider);
}

But I think there is no point in that. This code is much less clear and also not 100% percent bulletproof. I think it is worth to do only if you planning to add your own extension for type resolving, because styles added to resources either have Type.FullName key or just some arbitrary name as key. Previous solution is then sufficient. Below is sample application.

 StylesInheritance.zip (54.13 kb)

Also there is available public github repository with code for this article and other ones from Xamarin series.



Xamarin Frame and disappearing Outline

clock April 22, 2016 14:00 by author n.podbielski

This is another article in mini series of Xamarin bugs and workarounds for them Smile. Previous one you can find here.

This one is again about Frame control. I promise that another one will be about something else Cool.

Issue can be observed when you bind BackgroundColor property of Frame control and something will trigger change of view model source property binded to background color.

But since one image is more than thousand words - here is gif with this bug.

 

Frame is quite big, but if you look near corners of it, you will see, that there are round when background is green and when background change to Red, they disappear. Outline disappear too. It is slight white line around green field (it is even less visible), but I assure you that it is there. Smile

Ok here is a code for this example in xaml App file:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="FrameBug.App">
  <Application.MainPage>
    <ContentPage>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="*"></RowDefinition>
          <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <StackLayout Padding="10">
          <Frame VerticalOptions="Center" OutlineColor="White" 
                 BackgroundColor="{Binding LineColor}">
            <Label Text="Label" FontSize="60" />
          </Frame>
        </StackLayout>
        <Button Text="Change color" Grid.Row="1" Command="{Binding ChangeColor}"></Button>
      </Grid>
    </ContentPage>
  </Application.MainPage>
</Application>

One noticable thing done in code behind for this xaml file is adding BindingContext instance (App.xaml.cs file):

namespace FrameBug
{
    public partial class App
    {
        public App()
        {
            InitializeComponent();
            BindingContext = new AppViewModel();
        }
    }
}

Ok. One missing piece is AppViewModel class:

using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Xamarin.Forms;

namespace FrameBug
{
    public class AppViewModel : INotifyPropertyChanged
    {
        private ICommand _changeColor;

        public event PropertyChangedEventHandler PropertyChanged;

        public ICommand ChangeColor => _changeColor ?? (_changeColor = new Command(OnChangeColor));

        public Color LineColor { get; set; } = Color.Green;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnChangeColor()
        {
            LineColor = Color.Red;
            OnPropertyChanged("LineColor");
        }
    }
}

As you may notice it is C# code from VS2015. It will not work in prior versions, but there is not really point in doing test Xamarin apps in earlier versions since Xamarin recently was released for free even in VS2015 community edition.

With this simple application added to Xamarin template solution we can reproduce bug as in above gif. But how to fix it? And why it occurs? It took some digging and Resharper help with decompiling FrameRenderer to find out why. Yes, this class that renders Frame control as plain bitmap in Android environment is source of the problem. This class (since there is no public source code I will not include disassembled source code) have private UpdateBackground method which creates custom class based on Android Drawable class. It in its bowels it renders Background with solid color from BackgroundColor property of Frame control and Outline as a line (or rather rounded rectangle) from OutlineColor property of Frame. Those methods suppose to work either on initialization or BackgroundColor, OutlineColor properties change according to code of mentioned class. All good, right? When I created very similar class, attached it to custom renderer of Frame both operations was performed correctly during debugging session. But still frame was drawn incorrectly. It took some experimentation with height and width of rectangles in bitmap and it struck me that nothing happens even with 1x1 px size, because background is rerendered in some other place. Where? Since no more code in renderer was touching drawing it had to be in base class - VisualElementRenderer<>. If you disassemble it too, you will see that it have SetBackgroundColor and it was my first suspect. This method is executed on property change of control. Which one you ask? Smile BackgroundColor property. I did not dig any further since it is virtual method. Quick test proved my suspect guilty. Adding following override method to custom renderer fixed this problem.

public override void SetBackgroundColor(Color color)
{

}

Since code in FrameRenderer and its base class was executing correctly it probably was executing in wrong order. Probably it was missed by Xamarin Team after fixing this bug and closing this one. Or maybe this method as virtual was added after fix and tests and testers missed it? Nevertheless, writing new custom renderer based on Xamarin one fix this issue:

[assembly: ExportRenderer(typeof(Frame), typeof(FrameRenderer))]
namespace FrameBug.Droid
{
    public class FrameRenderer : Xamarin.Forms.Platform.Android.FrameRenderer
    {
        public override void SetBackgroundColor(Color color)
        {
            //base.SetBackgroundColor(color);
        }
    }
}

Commented line can be used to trigger the buggy behavior if anyone is curious enough Smile.

This is another one of mine unpleasant adventures with Xamarin framework. I hope this can be helpful and spare you some time. You can find sample application below.

FrameBug.zip (52.56 kb)

Also there is available public github repository with code for this article and other ones from Xamarin series.



Xamarin Frame and Style with Padding

clock April 22, 2016 06:10 by author n.podbielski

If you are a bit advanced with Xamarin you should already now that there is possibility of styling your controls almost like in WPF.
Almost, because there is a few strange bugs involving this. For example there is a problem with styling a Padding property in Frame. Consider following Xaml of Xamarin application (I tested it in Android):

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:styles="clr-namespace:Styles;assembly=Styles"
             x:Class="Styles.App">
  <Application.Resources>
    <ResourceDictionary>
      <Style TargetType="Frame" x:Key="Style">
        <Setter Property="Padding" Value="0" />
      </Style>
    </ResourceDictionary>
  </Application.Resources>
  <Application.MainPage>
    <ContentPage>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="100" />
            <RowDefinition Height="100" />
            <RowDefinition Height="100" />
          <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Frame VerticalOptions="Center"
               Grid.Row="0"
               Padding="0">
          <Label Text="100 height" FontSize="60" />
        </Frame>
        <Frame VerticalOptions="Center" Style="{StaticResource Style}"
               Grid.Row="1"
               Padding="0">
          <Label Text="100 height" FontSize="60" />
        </Frame>
        <Frame VerticalOptions="Center" Style="{StaticResource Style}"
               Grid.Row="2">
          <Label Text="100 height" FontSize="60" />
        </Frame>
      </Grid>
    </ContentPage>
  </Application.MainPage>
</Application>

It almost the same as default (created by template) shared application - but instead of App.cs we have more advanced Xaml file.

What not suspecting (or better: excepting a normal behavior) user would except all Frames to have the same view because properties will have the same values. Should have the same values, but they are not. This code will produce following layout:

 

Last Frame do not have explicit setting for Padding in its declaration and this property is resolved to default value and its contents just do not fit in available space. Why? There is a bug for that.

But according to comments Xamarin Team is not exactly willing to fix it.

Fortunately there is a quick workaround for that. The easiest thing to do is to just add this method to new class named i.e. FixedFrame:

public class ExtendedFrame : Frame
{
    protected override void OnPropertyChanged(string propertyName = null)
    {
        // ReSharper disable once ExplicitCallerInfoArgument
        base.OnPropertyChanged(propertyName);
        if (propertyName == StyleProperty.PropertyName)
        {
            if (Style.Setters.Any(s => s.Property == PaddingProperty))
            {
                Padding = (Thickness)Style.Setters.First(s => s.Property == PaddingProperty).Value;
            }
        }
    }
}

Using this class instead of original Frame from Xamarin framework will ensure proper Padding value after applying Style to FixedFrame control. Consider changed Android application from above, with added new FixedFrame control at the end. Only property set is Style and theer is no explicit value for Padding in control declaration:

<?xml version="1.0" encoding="utf-8" ?>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:styles="clr-namespace:Styles;assembly=Styles"
             x:Class="Styles.App">
  <Application.Resources>
    <ResourceDictionary>
      <Style TargetType="Frame" x:Key="Style">
        <Setter Property="Padding" Value="0" />
      </Style>
    </ResourceDictionary>
  </Application.Resources>
  <Application.MainPage>
    <ContentPage>
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="100" />
            <RowDefinition Height="100" />
            <RowDefinition Height="100" />
          <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Frame VerticalOptions="Center"
               Grid.Row="0"
               Padding="0">
          <Label Text="100 height" FontSize="60" />
        </Frame>
        <Frame VerticalOptions="Center" Style="{StaticResource Style}"
               Grid.Row="1"
               Padding="0">
          <Label Text="100 height" FontSize="60" />
        </Frame>
        <Frame VerticalOptions="Center" Style="{StaticResource Style}"
               Grid.Row="2">
          <Label Text="100 height" FontSize="60" />
        </Frame>
        <styles:FrameExt VerticalOptions="Center" Style="{StaticResource Style}"
               Grid.Row="3">
          <Label Text="100 height" FontSize="60" />
        </styles:FrameExt>
      </Grid>
    </ContentPage>
  </Application.MainPage>
</Application>

As a result we will have following window layout:

 

As you see last row with FixedFrame control have proper Padding property value. Smile
Simple and effective. Below sample application.

Styles.zip (324.08 kb)

Also there is available public github repository with code for this article and other ones from Xamarin series.



Safe cast string to enum

clock February 25, 2014 23:49 by author n.podbielski

In on of my projects I had make an interface between database and web service in C# code.

One of problem I had to face was need to cast strings to enumerable types, because of simple fact that database have no idea what is an 'enum'. Yes simplest mapping between an enumeration and database type is integer. It is simplest but in my idea not best. For example I really do not remember (or do not WANT to remember) what is the meaning of 4 integer value in case of package shipment status.

We can have values like this:

0 - RequestReceived
1 - Accepted
2 - Assembling
3 - Sended
4 - CustomerReceived
5 - Completed

Let's assume that is valid flow of package delivery flow. For someone that is working on system that handles monitoring of that kind of mechanism, this could be not an issue, because this flow is easy to recall. Yes. But as company grows, software grows. And most likely more enumeration types will be created.

So to have best of to worlds, in my opinion this is best to have enumeration in strings and with possibility to cast strings like '0' and 'RequestReceived' to RequestReceived enum value.

Nice feature is to make casting also case insensitive. But this is not necessary.

Aside from interfacing with database there are other use case that come to mind:

1. User interfaces input

2. Type serialization to JSON and from JSON

3. XML serialization

4. Import from various data sources like CSV

Ok. That is for introduction. Let's go to the coding.

First we have to retrieve values of enum type:

var values = Enum.GetValues(typeof(TEnum));

This is simple. Static method of Enum special class returns all possible values of an enum. With that knowledge we can just use foreach loop to iterate through collection:

public static EnumTest GetEnumValue(string val)
{
    var values = Enum.GetValues(typeof(EnumTest));
    foreach (EnumTest value in values)
    {
        if (val.Equals(value.ToString()))
        {
            return value;
        }
    }
    return 0;
}

There is a few problems with this method. For first: we can use it with only one predefined type of enum. Sadly this is impossible to create generic enum-only method in C#. But we can do pretty close. Second problem is that we don't have too have default value of enum type with integer equivalent of 0. 0 can not be in an enum at all!
 For first issue we can add generic type argument with constraints of interfaces implemented by enum types and with struct special constraint.
 For second issue we can use default C# keyword. Our 'better' method will be declared as following:

public static TEnum GetEnumValue(string val)
    where TEnum : struct, IComparable, IFormattable, IConvertible
{
    var values = Enum.GetValues(typeof(TEnum));
    foreach (TEnum value in values)
    {
        if (val.Equals(value.ToString()))
        {
            return value;
        }
    }
    return default(TEnum);
}

Of course there are can be other types that can work with this method but are in fact not an enumerable types, but this is best solution available in C# (that I know of). Default statement in case where string value is not found in method will return first defined value of an enum.

Next step will be add possibility of integers values in strings. For that we have to cast enum values to type int. We cannot do that with simple casting operation in C#, because it is not possible with generic type we defined in our improved method. But we can use IConvertible interface and its ToInt32 method. It requires format provider for casting though. I used CultureInfo.CurrentCulture property which was OK in my application, but this could be a problem in others. It depends where it will be used. Changed method will look like this:

 

public static TEnum GetEnumValue2(string val)
    where TEnum : struct, IComparable, IFormattable, IConvertible
{
    var values = Enum.GetValues(typeof(TEnum));
    foreach (TEnum value in values)
    {
        if (val.Equals(value.ToString())
            || val == (value.ToInt32(CultureInfo.CurrentCulture)).ToString())
        {
            return value;
        }
    }
    return default(TEnum);
}

This mostly work ok, but this might be a problem when it is used like this:

package.Status = GetEnumValue<PackageStatus>(newStatusString);

Why? Because when newStatusString value is not proper value for and enum, status property will reset to default status value. It might be a problem. Solution might be exception throwing when value is invalid. This would be good for UI. I decided to use custom default value:

package.Status = GetEnumValue(newStatusString, package.Status);

This way status will not change if value in string is inalid and old value will be assigned.

Finally I added case insensitivity for string comparison. There are plenty of possibilities to do that in .NET so this is something that should be considered in regards of application which will be using that code. For example we can do something like this:

public static TEnum GetEnumValue2(string val,TEnum current)
where TEnum : struct, IComparable, IFormattable, IConvertible
{
    var values = Enum.GetValues(typeof(TEnum));
    foreach (TEnum value in values)
    {
        if (val.Equals(value.ToString(), StringComparison.OrdinalIgnoreCase)
            || val == (value.ToInt32(CultureInfo.CurrentCulture)).ToString())
        {
            return value;
        }
    }
    return current;
}

Nice have feature is to defined this method as extension method for string. This way we can call it after writing name of the variable with our string value.

package.Status = newStatusString.GetEnumValue(package.Status);

I prefer to do this that way, because it is more expressive to my coding style. While writing solution for some kind of a problem I think: I want here this value but after mapping it in the following way. With using method GetEnumValue as a plain method not extension, it is in my opinion greater burden for someone who read code (which is mostly me and I always want to make my life easier :) ). But this is subject of another article.

Anyway this can be achieved just by adding this keyword and placing method in separate class.

public static class Extension
{
    public static TEnum GetEnumValue( this string val, TEnum current)
where TEnum : struct, IComparable, IFormattable, IConvertible
    {
        var values = Enum.GetValues(typeof(TEnum));
        foreach (TEnum value in values)
        {
            if (val.Equals(value.ToString(), StringComparison.OrdinalIgnoreCase)
                || val == (value.ToInt32(CultureInfo.CurrentCulture)).ToString())
            {
                return value;
            }
        }
        return current;
    }
}

This is very simple solution for this particular problem. There are more thing that can be changed/improved. You can download code sample and play with it yourself :)

Enjoy!

 Program.cs (3.55 kb)



Visual Studio code snippets

clock February 25, 2014 12:39 by author n.podbielski

What I really like in Visual Studio as development environment is code snippets. Well actually probably other IDE have something very similar but I do not have much of a choice in that matter as C# developer :)
Anyway this feature is really useful. For example while refactoring I very often use if surround snippet.

Unfortunately there are no easy way to edit/add new snippets since VS do not have built in snippets editor. But their syntax is almost XML and quite simple. I will cover few simple examples in this short article.

Ok. Let's start with what we have in VS. There is Code Snippets Manager available Tool menu.

 

There is not much we can do in that window: add or remove snippets directory or import single snippets. In my opinion only real useful feature is possibility to check where we can find existing snippets. Also I do not recommend to add new folders because of extra need to specify search directory when we search for desired snippet after using insert snippet Visual Studio shortcut (Ctrl K, X by default for Visual C# environment setting). For example when selecting for surround statement in Java Script; after adding new folder we have to choose folder before we choose snippet, which is waste of time for me.

 Ok. Let's try a simple example. While developing in Java Script it is good idea to use Require JS or other AMD library.
 It would be really painful to write every time same formula for new JS module. Instead it is better to create code snippet. Using Code Snippets Manager we can obtain directory in which JS snippets resides. By default this is: C:\Program Files (x86)\Microsoft Visual Studio 11.0\JavaScript\Snippets\1033\JavaScript for VS 2012.

Desired code for starting a new module for me was:

define([''],
    function (dep) {	
        return new function () {
			//private variables
			//private functions
			//public functions
			$selected$$end$
			//globals
			//onload
		};
    });

To define code snippet with above template we have to create new file {name}.snippet in above directory.

File contents should be similar to following:

  
<CodeSnippet Format="1.1.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <Header>
    <Title>module</Title>
    <Author>Natan Podbielski</Author>
    <Shortcut>mdl</Shortcut>
    <Description>Code snippet Require JS module</Description>
    <SnippetTypes>
      <SnippetType>Expansion</SnippetType>
      <SnippetType>SurroundsWith</SnippetType>
    </SnippetTypes>
  </Header>
  <Snippet>
    <Code Language="JavaScript"><![CDATA[
define([''],
    function (dep) {	
        return new function () {
			//private variables
			//private functions
			//public functions
			$selected$$end$
			//globals
			//onload
		};
    });
]]></Code>
  </Snippet>
</CodeSnippet>

Keep in mind that white space in <Code> tag are very meaningful and should look exactly like it should look in destination code in VS. With file like this you can use it in VS. Press insert snippet shortcut in JS file. You should see something like this (sometimes it is necessary to open Code Snippets Manager or restart VS to force to reread all snippets):

 

 

 

Quick explanation about tags:

<Title> is a title that is shown in Code Snippet Manager and 'select snippet menu'.

<Author> is an author of the snipper. Visible in Code Snippet Manager.

<Shortcut> is a string of characters you have to type which make available to you Tab shortcut which will expand typed characters into desired code from snippet. Like ctor is a shortcut for built in VS constructor snippet.

<Description> is a description visible from Code Snippet Manager and from 'select snippet menu'.

<SnippetTypes> is an enumeration of snippet type. There is only two types of snippets: Expansion and SurroundsWith. With <SnippetType> tag you can decide which is it and from what menu or shortcut it will be available.

<Code> is an actual code for snippet. Should be 1 to 1 to desired code. Besides snippets variables which I will describe bellow.

 

You should be very specific about white space, indentation of code of snippet (about syntax too of course but it is obvious) etc. It is better to write it right once in snippet than correct it every time you use it :)

There are available plenty of variables inside of snippet. They are defined like $name$ inside actual code.

Most important for example for surround type of snippets is variable $selected$, which describe where VS should put text that you selected before inserting desired template. $end$ specifies when cursor should be after inserting snippet. It is useful for snippets that you should populate with specific code, method for example: you should write method body so this is useful to put $end$ inside method body. There are some variables defined by snippet engine, like $classname$, which is current class name. You can also defines your own variables, which then can be easily changed while using snippet. Consider built in snippet for property with backing field: propfull.

It has declaration as follows:

		<Snippet>
			<Declarations>
				<Literal>
					<ID>type</ID>
					<ToolTip>Property type</ToolTip>
					<Default>int</Default>
				</Literal>
				<Literal>
					<ID>property</ID>
					<ToolTip>Property name</ToolTip>
					<Default>MyProperty</Default>
				</Literal>
				<Literal>
					<ID>field</ID>
					<ToolTip>The variable backing this property</ToolTip>
					<Default>myVar</Default>
				</Literal>
			</Declarations>
			<Code Language="csharp"><![CDATA[private $type$ $field$;

	public $type$ $property$
	{
		get { return $field$;}
		set { $field$ = value;}
	}
	$end$]]>
			</Code>
		</Snippet>

Declaration of variables $type$ and $field$ allow us to write name of field and type of field and property one time in one place:

 

Changing myVar for something more meaningful and submitting a snippet will change highlighted places with myVar value inside snippet code too. Pretty useful!

As you can see in actual declaration of snippet variables there is possibility of setting default value and tool tip so and end user could know what we meant for variable while creating a template. There is a really world of possibilities from such snippets. If we using some kind of elaborate code structures inside of our project (custom data contracts for example, or ASP.NET custom controls etc.) it is best to create snippets for them. Or for other broadly used code samples.

For example I created snippet for jQuery ready function:

 <CodeSnippet Format="1.1.0" xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <Header>
    <Title>jQuery ready</Title>
    <Author>Natan Podbielski</Author>
    <Shortcut>docrd</Shortcut>
    <Description>Code snippet for jQuery document ready event</Description>
    <SnippetTypes>
      <SnippetType>Expansion</SnippetType>
      <SnippetType>SurroundsWith</SnippetType>
    </SnippetTypes>
  </Header>
  <Snippet>
    <Code Language="JavaScript"><![CDATA[$$(function(){
	$selected$$end$
});]]></Code>
  </Snippet>
</CodeSnippet>

Important: as you can see above to achieve $ inside destination code (after using a snippet inside VS) you have to escape it with $, so jQuery $ becomes $$ inside snippet code declaration!

Or for console.log(); JS function, which is very similar but with <Code> tag like this:

 <Code Language="JavaScript"><![CDATA[console.log($end$);]]></Code>

I hope this will help in your journey into VS code snippets world. :)



Smart string builder

clock February 22, 2014 04:16 by author n.podbielski

In this rare times when I was writing code that suppose to create large string from smaller chunks and with some non string parameters I was using StringBuilder class of course. Of course because string adding, or string concatenation is very costly when talking about memory utilization. It is because every time you do this:

var text = "Hello world!"+ "\n"+ "How are you?";

new string is created for every '+' operation in memory. Not a best way of doing strings creations. StringBuilder is better because it do not creates strings until you call .ToString method of StringBuilder class.

So instead of doing something like was shown above code should look something like follows:

var stringBuilder = new StringBuilder();
stringBuilder.Append("Hello world!");
stringBuilder.Append("\n");
stringBuilder.Append("How are you?");
Console.WriteLine(stringBuilder);

This is better but while writing this code I disliked of how much you have to type to just add another string to string builder object. I thought: can this be done better? In fact it can. And this is way I created SmartStringBuilder class.

Requirement was to have something like this:

var smartBuilder = new SmartStringBuilder();
smartBuilder += "Hello World!";
smartBuilder += "\n";
smartBuilder += "How are you?";
Console.WriteLine(smartBuilder);

Luckily C# alows to write custom behaviors for operators like '+'. To do this we can use special operator keyword in C#. For managing chunks of strings we will use private instance of StringBuilder class:

public class SmartStringBuilder
{
    private StringBuilder internalStringBuilder = new StringBuilder();

    public SmartStringBuilder() { }

    public SmartStringBuilder(string str)
    {
        internalStringBuilder.Append(str);
    }

    public override string ToString()
    {
        return internalStringBuilder.ToString();
    }

    public static SmartStringBuilder operator +(SmartStringBuilder smartBuilder, string addString)
    {
        smartBuilder.internalStringBuilder.Append(addString);
        return smartBuilder;
    }
}

This allows us to execute first 3 lines of 'requirements code'

var smartBuilder = new SmartStringBuilder();
smartBuilder += "Hello World!";
smartBuilder += "\n";
smartBuilder += "How are you?";

To allows using our new class us string in Console.WriteLine method (or any other method that takes string parameter) we need to add implicit casting operator to string type:

public static implicit operator string(SmartStringBuilder smartBuilder)
{
   return smartBuilder.ToString();
}

With our class defined like this we can execute following line:

Console.WriteLine(smartBuilder);

Another nice feature is possibility of adding values of other types to our builder with + sign. We can do this by adding + operator to our class for each of them. For example for int type this method would look like this:

public static SmartStringBuilder operator +(SmartStringBuilder smartBuilder, int number)
{
    smartBuilder.internalStringBuilder.Append(number);
    return smartBuilder;
}

This allows us to execute following line safely:

smartBuilder += 1;

Ideally would be to add possibility of formatting values of other types with format strings i.e.:

smartBuilder += ("format {0}", 1);

But this is impossible without changing C# language itslelf. Best thing we can do is to add AppendFormat method that executes method with the same name in internal StringBuilder object.

public void AppendFormat(string format, params object[] parameters)
{
     internalStringBuilder.AppendFormat(format, parameters);
}

Our whole class will look like this:

public class SmartStringBuilder
{

    private StringBuilder internalStringBuilder = new StringBuilder();

    public SmartStringBuilder() { }

    public SmartStringBuilder(string str)
    {
        internalStringBuilder.Append(str);
    }

    public override string ToString()
    {
        return internalStringBuilder.ToString();
    }

    public static implicit operator string(SmartStringBuilder smartBuilder)
    {
        return smartBuilder.ToString();
    }

    public static SmartStringBuilder operator +(SmartStringBuilder smartBuilder, string addString)
    {
        smartBuilder.internalStringBuilder.Append(addString);
        return smartBuilder;
    }

    public static SmartStringBuilder operator +(SmartStringBuilder smartBuilder, int number)
    {
        smartBuilder.internalStringBuilder.Append(number);
        return smartBuilder;
    }

    public void AppendFormat(string format, params object[] parameters)
    {
        internalStringBuilder.AppendFormat(format, parameters);
    }
}

That is it. Not much of magic but it simplifies string manipulation a little Smile.



Expression parsing and nested properties

clock February 22, 2014 04:00 by author n.podbielski

In one of projects I was working on, I needed to get property value from property path and property path from expression.

First, lets cover second case.

With expression in form of nested property value:

()=>object1.object2.object3.object4

we cannot take simple value of some property, because we have only root object, object1.

Instead we have to take every value of every object in the middle and last object as value od our desired property.

If we would have expression like this:

()=>object1.object2

and value of root object (object1), we can just cast expression above to MemberExpression type and then retrieve name of the property, from property MemberExpression.Member.Name.

But if we need another property of object3 or even deeper, we need to retrieve another, nested MemberExpression from expression above.

Without knowledge of depth of our expression, we had to repeat that operation as long as property MemberExpression.Expression has value different than null.

To take MemberExpression from given Expression (which can be of many types: MemberExpression, LambdaExpression, UnaryExpression) we can use following method:

public static MemberExpression GetMemberExpression(Expression expression)
{
    if (expression is MemberExpression)
    {
        return (MemberExpression)expression;
    }
    else if (expression is LambdaExpression)
    {
        var lambdaExpression = expression as LambdaExpression;
        if (lambdaExpression.Body is MemberExpression)
        {
            return (MemberExpression)lambdaExpression.Body;
        }
        else if (lambdaExpression.Body is UnaryExpression)
        {
            return ((MemberExpression)((UnaryExpression)lambdaExpression.Body).Operand);
        }
    }
    return null;
}

 

This method will return MemberExpression from any of above types.

Armed with method like this we can write loop to retrieve property name for all levels of expression. For example we can use rarely used do...while loop. Of course we can use while loop, but this way we can have additional learning experience, using less known language constructs :)

 

public static string GetPropertyPath(Expression expr)
{
    var path = new StringBuilder();
    MemberExpression memberExpression = GetMemberExpression(expr);
    do
    {
        if (path.Length > 0)
        {
            path.Insert(0, ".");
        }
        path.Insert(0, memberExpression.Member.Name);
        memberExpression = GetMemberExpression(memberExpression.Expression);
    }
    while (memberExpression != null);
    return path.ToString();
}

In my code I placed those two methods in one class called ExpressionOperator and then used them in extension for type Object:

public static string GetPropertyPath<TObj, TRet>(this TObj obj, Expression<Func<TObj, TRet>> expr)
{
    return ExpressionOperator.GetPropertyPath(expr);
}

which can be used like this:

object1.GetPropertyPath(o =>o.object2.object3.object4)

which should return "object2.object3.object4" string. With possibility for returning a property path from any expression, we can now write method that returns value of destination property (last in the expression).

Method like this is even simpler than for returning property path. We just need to find value of every property in the middle of path to the point, when we have our destination property. For that we can use while loop :)

public static object GetPropertyValue(this object obj, string propertyPath)
{
    object propertyValue = null;
    if (propertyPath.IndexOf(".") < 0)
    {
        var objType = obj.GetType();
        propertyValue = objType.GetProperty(propertyPath).GetValue(obj, null);
        return propertyValue;
    }
    var properties = propertyPath.Split('.').ToList();
    var midPropertyValue = obj;
    while (properties.Count > 0)
    {
        var propertyName = properties.First();
        properties.Remove(propertyName);
        propertyValue = midPropertyValue.GetPropertyValue(propertyName);
        midPropertyValue = propertyValue;
    }
    return propertyValue;
}

Above code returns value of property by reflection. Property name is taken by splitting property path into parts separated by '.'. For example we can use this method in a following way:

object1.GetPropertyValue(o=>o.object2.object3.object4);

This is really simple example. For better usability you should add validating for root object (if this object have value in the first place) and for any of mid-objects. They did not have to have value too, they could not have value because of lack of initialization of object tree. Also good idea is to add boolean flag, if we want method to return an error in above cases or false (lack of success) and null value (value of desired property).

Another way to improve things is to add similar way to retrieve type of nested property or set property value by property path given as string.

In project I was working on I used this mechanism to retrieve properties path in C# code, transport it to client (it was web application so client was a browser) and set property value in JavaScript object, which had the same object tree. In other way I transported value of changed property at the client side and its path, to apply changes at server side. Very useful to synchronize two different data schemes.

Attached to this article is example console application for retrieving property path and property value of a nested property.

 Program.cs (3.78 kb)

I hope this will help :)



WebSocket libraries comparison

clock February 21, 2014 15:38 by author n.podbielski

 

Web project often requires to push data to clients as fast as possible, whenever it is necessary without waiting for client request. It is perfect for website with real time communication between users, like with online communicators for example. Or document collaboration tools. Or maybe system status updates on long running calculation/tasks performed by server. In every case two way communication mechanism is ideal.

Before, following solution was used for this kind of problems:

 

 

But now we have something better: WebSocket. Standard is implemented for some time now in modern browsers. It was released in 2011, which is even better because with changes and upgrades with have more secure and mature protocol.</>

 

Few remarks:

Comparison was made few months ago and can be outdated a bit, but I think that is still useful if anyone will be looking for good WebSocket library.

Only libraries published as NuGet packages was taken into account, beside one, SuperWebSocket which I found using NuGet repository, but it was needed to download from web page anyway.

Maybe if I will find time, I will update this article with new libraries or new version of already tested libraries.

 

  1. Fleck

    https://github.com/statianzo/Fleck


    I did found it really simple to install and use. I did not have any problems with library, documentation, examples etc. Just add package, copy some samples and run project. Simple.

    But with simplicity there is a price: it is not very powerful nor configurable solution.

    private static void Main(string[] args)
    {
         var server = new WebSocketServer("ws://localhost:8181");
         server.Start(socket =>
         {
              socket.OnOpen = () => OnOpen(socket);
              socket.OnClose = () => OnClose(socket);
              socket.OnMessage = m => OnMessage(socket, m);
         });
    }

    I would use this library for quick or simple project. If you do no need complex data structure to be send through WebSocket, command-like messages, many servers or fallback when you client do not have WebSocket support, this may be library for you.

    Advantages:

    • Simple
    • No dependencies

    Disadavantages:

    • Not very configurable
    • No fallback in case your browser do not support WebSocket

  2. SignalR

    http://www.asp.net/signalr


    It is library from Micrsoft which I personally treat as advantage. It has integration with existing framework, ASP.NET and good abstraction for both: client and server code. It means that you do not have to know much about a protocol which is good. And it is able to fallback gracefully to other communication mechanism whenever your client cannot use WebSocket. Also it is possible to accomplish something that is called Remote Procedure Call, from server to client.

    It can broad cast data to all clients or send message to only one. And scale to really great number of simultaneous connections. And is open source!

    Sounds really great, right? Yeah... except it needs IIS8 on Windows Server 2012 (or Windows 8 for that matter, but you would not host any really big project on that system, right?). For me it is one of cool features of ‘Microsoft-new-server-OS-which-you-should-buy’. It is not bad if you want to develop enterprise project, but for small projects this library is too expensive even if it is open source.

    Of course this requirements are actually needed if you want WebSocket communication. But this article is about WebSocket communication, so I count this as really big disadvantage.

    public class MyHub1 : Hub
    {
        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }
    } 
    $(function () {
        var chat = $.connection.myHub1;
        chat.client.broadcastMessage = function (name, message) {
            //...
        };
        $.connection.hub.start().done(function () {
            $('#sendmessage').click(function () {
                chat.server.send('message');
            });
        });
    });

     

    Advantages:

    • Good abstraction
    • Good integration with IIS and ASP.NET
    • Many fallbacks
    • Open source
    • Microsoft library
    • Scallable

    Disadvantages:

    • IIS 8 required…
    • … which needs very expensive server OS, Windows Server 2012


  3. AlchemyWebSocket

    http://alchemywebsockets.net/

     

    This one do not really comes to mind when I recall WebSocket libraries. There is nothing wrong with this one really. It can be placed right behind Fleck. It is also really simple, easy to use, easy to install (Nuget package available) and has documentation with good examples.

    It has server part and client part code built-in. It is also scalable.

    static void Main(string[] args)
    {
        // instantiate a new server - acceptable port and IP range,
        // and set up your methods.
    
        var aServer = new WebSocketServer(81, IPAddress.Any)
        {
            OnReceive = OnReceive,
            OnSend = OnSend,
            OnConnect = OnConnect,
            OnConnected = OnConnected,
            OnDisconnect = OnDisconnect,
            TimeOut = new TimeSpan(0, 5, 0)
        };
    
        aServer.Start();
        string consoleReadLine;
        do
        {
            consoleReadLine = Console.ReadLine();
            sockets.ForEach(s => s.Send(consoleReadLine));
        } while (consoleReadLine != "exit");
    }

     

    But it also have some awkwardness, that I cannot shake off. For example there is no simple event method “OnReceive” with just string, with actual message that was sent from client. You have to do it yourself. Yes, you have to call only .ToString() to get actual message, but whole point of using a library is to not force yourself to thing about how communication protocol is implemented.


    private static void OnReceive(UserContext context) { Console.WriteLine("Client " + context.ClientAddress.ToString() + " sended: " + context.DataFrame.ToString()); }

     

    WebSocket server initialization method takes first port and then IP setting. I always thinks, in terms of address as IP and THEN port, if port is necessary. Or timeout setting: why there is timeout anyway? I can understand that it may be sometimes useful, but as a feature not as one of primary settings. But those are details really.

    For me this force your code to abstract it away, with another layer of code, which should be done by this library in the first place.

    Anyway you can try it out, compare performance to Fleck, and decide which would be better for your simple project.

     

    Advantages:

    • Simple
    • No dependencies
    • Good documentation

    Disadvantages:

    • A bit awkward and little more complicated from Fleck
    • No fallback


  4. XSockets

    http://xsockets.net/


    This one seemed really promising. I really tried and spend much more time, trying to make it work than on other libraries (even with performance tests etc). But I had no luck unfortunately. Really, anything I can think of which can be wrong with library is wrong with this one. Bad documentation which differs from code. Which one is outdated? Code or documentation? It is not easy to install and get it running. In fact this library has examples that I had hard time to build and run. Or examples that you could say, shows more about MVC framework then about XSockets library itself. I tried to run this inside ASP.NET project, MVC and WinService. Sadly none of them worked.

    I really hoped for this one but eventually give up in favor of better (read any other) library. Seriously, why use library that is hard to even start simple project? You can predict more issues to come while actually using it inside a project. I recommend to stay away from this project.

     

    public static class XSocketsBootstrap
    {
        private static IXBaseServerContainer wss;
        public static void Start()
        {            
            wss = XSockets.Plugin.Framework.Composable.GetExport();
            wss.StartServers();
        }
    }


    Advantages:

    • Seems powerful
    • Should have good JavaScript integration

    Disadvantages:

    • Complicated and hard
    • Complicated to configure and run inside of WebForms, MVC and WinService
    • Differences between code and documentation
    • Outdated documentation and examples


  5. Microsoft.WebSocket

    http://msdn.microsoft.com/en-us/hh969243.aspx


    Another library from Microsoft. And it requires IIS 8 too, so I did not have means to test it. Examples are really low level, so it force you to deal with buffers and streams instead of strings. In some cases this can be good, but mostly there is no point. If you have IIS 8 on server why bother with this library if you can use SignalR, which will take care most of the stuff for you.

    I think this is more of proof-of-concept then usable library.

    int count = receiveResult.Count;
    
    while (receiveResult.EndOfMessage == false)
    {
        if (count >= maxMessageSize)
        {
            string closeMessage = string.Format("Maximum message size: {0} bytes.", maxMessageSize);
            await socket.CloseAsync(WebSocketCloseStatus.MessageTooBig, closeMessage, CancellationToken.None);
            return;
        } receiveResult = await socket.ReceiveAsync(new ArraySegment(receiveBuffer, count, maxMessageSize - count), CancellationToken.None);
        count += receiveResult.Count;
    } var receivedString = Encoding.UTF8.GetString(receiveBuffer, 0, count);
    var echoString = "You said " + receivedString;
    ArraySegment outputBuffer = new ArraySegment(Encoding.UTF8.GetBytes(echoString));
    await socket.SendAsync(outputBuffer, WebSocketMessageType.Text, true, CancellationToken.None);

     

  6. SuperWebsocket

    http://superwebsocket.codeplex.com/

    Last but not least is SuperWebsocket. I was a bit skeptical about this one (if I remember correctly this is only one package that I somehow found through NuGet website but is not available as a package). It may seems a little complicated, but in fact it is very easy. Examples supported by documentation takes you step by step from simplest WebSocket servers, to more complicated ones, with command requests, JSON, multiple servers instances, .config file configuration and more.

    This library maybe do not have all cool features that other does, but it does not matter because it is very configurable and easy to make it do what you want to. It can work in ASP.NET, as console application, and windows service. Documentation however recommends running server as system service. I from my experience recommend not running it inside web application because of slowness of such solution (very bad performance, about fifty times slower than console app). From other hand standalone application with server, requires to run .exe that is not strictly part of library, but part of SuperSocket project (on which SuperWebSocket is based). This force you to do a little ‘magic’ to start server with debug session, or to enable debug at all. When you run server as application which is not strictly part of solution, there is also issue with forcing server to use latest version of assemblies from other projects.

    In return you get well known solution for flexible WebSocket.

    It is also open source so you can change something if you want.

    From the other hand, as a disadvantage you can count lack of JavaScript client for this server (but there is C# client). Also this one has third party dependencies.

    After working with this library for few months I do not know about any major issues.

     

    Advantages:

    • Nice fetueres and very configurable
    • Great examples
    • Example (with documentation of recommended setup)
    • Can work as WinService and inside ASP.NET and console app
    • Good performance

    Disadvantages:

    • No fallback communication
    • Dependencies

     


Summary:

For complicated solutions/projects I recommend use of SuperWebSocket which is stable and very configurable library. For simple and fast projects I would choose Fleck, but I would give up both for SignalR if have means to use latest Windows Server as machine for tests and production.

 

Projects:

Test projects I was using to compare libraries you can find here:

WebSocketTest.zip



Ninject and WCF

clock May 26, 2013 13:01 by author n.podbielski

Ninject is very simple and in the same time powerful IoC container. I used it in few project and had very little or none problems.

Most of the time getting instances from Ninject kernel requires simple line with binding expression, or even this is sometime unnecessary if type is self bind able (i.e. if it is concrete class with parameterless constructor).

Little harder is getting Ninject to work with WCF. You cannot just bind interfaces types because proxies which implements them are created through .NET mechanism. Luckily WCF system is very flexible and mostly can be changed/extended with custom functionality.

How we can do that? Best solution is to add new behavior for our WCF services. Behavior is a class that implements IServiceBehavior interface. ApplyDispatchBehavior  method accessible through that interface allow our code to change instance provider of our service. Instance provider on the other hand is object with IInstanceProvider interface implementation and GetInstance method. This method is defined in following way:

object GetInstance(InstanceContext instanceContext);
object GetInstance(InstanceContext instanceContext, Message message);

 

Inside one of them we can create instance of our service from Ninject container.

Let us start from the top, with behavior class. It can be applied to service from attribute.

public class NinjectBehaviorAttribute : Attribute, IServiceBehavior
{
	public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
				Collection endpoints, BindingParameterCollection bindingParameters)
	{
	}

	public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
	{
		Type serviceType = serviceDescription.ServiceType;
		IInstanceProvider instanceProvider = new NinjectInstanceProvider(NinjectServiceLocator.Kernel, serviceType);

		foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers)
		{
			foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints)
			{
				DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime;
				dispatchRuntime.InstanceProvider = instanceProvider;
			}
		}
	}

	public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
	{
	}
}

All interesting things happens inside of ApplyDispatchBehavior method. First is created NinjectInstanceProvider class, to which is passed instance of Ninject kernel, and our desired service type information. Instance provider is defined as following:

public class NinjectInstanceProvider : IInstanceProvider
{
	private Type serviceType;
	private IKernel kernel;

	public NinjectInstanceProvider(IKernel kernel, Type serviceType)
	{
		this.kernel = kernel;
		this.serviceType = serviceType;
	}

	public object GetInstance(InstanceContext instanceContext)
	{
		return this.GetInstance(instanceContext, null);
	}

	public object GetInstance(InstanceContext instanceContext, Message message)
	{
		return kernel.Get(this.serviceType);
	}

	public void ReleaseInstance(InstanceContext instanceContext, object instance)
	{
	}
}

Inside second overload of GetInstance method is created actual service instance, through Ninject kernel. Ninject kernel is acquired from simple implementation of service locator. It's just static class with public read only property with Ninject kernel.

public static class NinjectServiceLocator
{
	public static IKernel Kernel { get; private set; }

	public static void SetServiceLocator(IKernel kernel)
	{
		Kernel = kernel;
	}
}

Instance of kernel is injected into property with SetServiceLocator method after initialization, preferably inside NinjectWebCommon class, which is created in App_Start directory after adding Ninject to project from NuGet.

private static IKernel CreateKernel()
{
	var kernel = new StandardKernel();
	kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
	RegisterServices(kernel);
	NinjectServiceLocator.SetServiceLocator(kernel);
	return kernel;
}

I decided to go with this solution instead of actual implementation of Microsoft ServiceLocator class to keep it simple, which in fact is working in similar way.

After creating instance provider object, we apply it to all endpoints inside ApplyDispatchBehavior.

Last thing is to actually registering service types inside Ninject. Typically we are creating all data necessary to make service proxy inside web.config file. WCF channel can be created from such configuration with ChannelFactory class. Lets implement this functionality inside class that implements Ninject.Activation.Provider<T> type available from Ninject assembly.

public class ConfigServiceProvider<TService> : Provider<TService>
{

	protected override TService CreateInstance(IContext context)
	{
		var @interface = typeof(TService);
		var interfaceTypeName = @interface.FullName;
		var endpointsConfig = (ClientSection)ConfigurationManager.GetSection("system.serviceModel/client");
		string address = null;
		foreach (ChannelEndpointElement endpoint in endpointsConfig.Endpoints)
		{
			if (endpoint.Contract == interfaceTypeName)
			{
				address = endpoint.Address.OriginalString;
				break;
			}
		}
		var factory = new ChannelFactory<TService>(new WSHttpBinding(), address);
		return factory.CreateChannel();
	}
}

First provider is accessing configuration of all services, then searching inside of configuration for matching interface type name. If finds one, address of WCF service endpoint is passed to ChannelFactory class which will create service proxy. With such provider we can do actual type binding inside Ninject module:

public class WcfModule : NinjectModule
{
	public override void Load() { }

	public IBindingWhenInNamedWithOrOnSyntax BindServiceFromConfig()
	{
		return Bind().ToProvider<ConfigServiceProvider>();
	}
}

public class ServicesModule : WcfModule
{
	public override void Load()
	{
		BindServiceFromConfig();
	}
}

WcfModule class can be placed inside some library so we can use it in more than project. I am sure that not only one of them is using WCF services Smile. ServicesModule on the other hand should be placed inside assembly with services interfaces and loaded from NinjectWebCommon class inside WCF project.

And that is all. WCF web application registers services interfaces inside Ninject, creates kernel and setting its instance inside our custom ServiceLocator class. After that when service instance is accessed from .NET framework, NinjectBehaviorAttribute do its magic and acquires instance of NinjectInstanceProvider class, which is asking for instance of specified service from kernel. Kernel from its binding creates ConfigServiceProvider through one is created actual instance of proxy thanks to our configuration.