dotvvm - Open source MVVM framework for Web Apps DotVVM - Open source MVVM Framework for Web Apps

DotVVM with SignalR - client side connection is always undefined

I am trying to run signalR with DotVVM framework and I have problem with connection to my sample hub.

Here is my js code where I have a problem. $.connection is always undefined so I cant make any connection to my SignalR Hub and thats weird. Is it possible to use SignalR with DotVVM framework?

$(function () {
    var connection = $.connection.testHub();
    var proxy = connection.createHubProxy("testHub");

    proxy.client.hello = function (message) {

Scripts registration

<script src="~/AdminTemplate/Components/jquery/dist/jquery.min.js"></script>
<script src="~/AdminTemplate/Scripts/jquery.signalR-2.2.2.js"></script>
<%--<script src="~/signalr/hubs"></script>--%>
<script src="~/Hubs/Scripts/test.js"></script>

Here is my simple hub which only sends some string

public class TestHub : Hub
    public void Hello()
        var message = "test";

Startup class

public void Configuration(IAppBuilder app)
    var compositionRootFactory = new CompositionRootFactory();
    var container = compositionRootFactory.CreateContainer();

    var serviceInitializer = container.Resolve<ServicesInitializer>();

    var applicationPhysicalPath = HostingEnvironment.ApplicationPhysicalPath;


    app.UseCookieAuthentication(new CookieAuthenticationOptions
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Login"),
        Provider = new CookieAuthenticationProvider
            OnApplyRedirect = e => DotvvmAuthenticationHelper.ApplyRedirectResponse(e.OwinContext, e.RedirectUri)

    // use DotVVM
    var dotvvmConfiguration = app.UseDotVVM<DotvvmStartup>(applicationPhysicalPath, options: options =>

        options.Services.AddSingleton<IViewModelLoader>(serviceProvider => new WindsorViewModelLoader(container));

        options.AddUploadedFileStorage("App_Data/Temp", TimeSpan.FromSeconds(30));

    #if !DEBUG
        dotvvmConfiguration.Debug = false;

Source: (StackOverflow)

How to use Kendo UI Grid with DotVVM ViewModel?

Having the following ViewModel in DotVVM:

public class KendoGridViewModel : DotvvmViewModelBase
    public List<Product> Products { get; set; }

    public override Task Load()
        Products = GetItems();

        return base.Load();

    private static List<Product> GetItems()
        return new List<Product>
            new Product {OrderID = 1, ShipName = "Product 1", Freight = 100},
            new Product {OrderID = 2, ShipName = "Product 2", Freight = 200},
            new Product {OrderID = 3, ShipName = "Product 3", Freight = 300},
            new Product {OrderID = 4, ShipName = "Product 4", Freight = 400},
            new Product {OrderID = 11, ShipName = "Product 1", Freight = 100},
            new Product {OrderID = 22, ShipName = "Product 2", Freight = 200},
            new Product {OrderID = 33, ShipName = "Product 3", Freight = 300},
            new Product {OrderID = 44, ShipName = "Product 4", Freight = 400},
            new Product {OrderID = 111, ShipName = "Product 1", Freight = 100},
            new Product {OrderID = 222, ShipName = "Product 2", Freight = 200},
            new Product {OrderID = 3333, ShipName = "Product 3", Freight = 300},
            new Product {OrderID = 4444, ShipName = "Product 4", Freight = 400},
            new Product {OrderID = 11111, ShipName = "Product 1", Freight = 100},
            new Product {OrderID = 22222, ShipName = "Product 2", Freight = 200},
            new Product {OrderID = 33333, ShipName = "Product 3", Freight = 300},
            new Product {OrderID = 44444, ShipName = "Product 4", Freight = 400},

What steps should be followed in order to integrate the KendoUI Grid knockout sample?

How the post-backs for the grid actions: read, update, create can be triggered?

Thank you!

Source: (StackOverflow)

Redirect all the not found routes in dotvvm

How can I redirect all not found page requests to the same view?

This illustrates somehow what I mean:

config.RouteTable.Add("Home", "*", "Views/Home.dothtml", new { });

The idea behind is that when someone accesses a not existing page:


The resquest is redirected to


Source: (StackOverflow)

Global object in DotVVM (for masterpage)

I'm looking for some global object in DotVVM framework as ViewBag in Asp.Net MVC. I wanna have a masterpage with dynamic title and I don't know how could I do this.

For example: In asp.net MVC "ViewBag.Title" -> where Title is property from view(model) and when I am changing articles, title changes too.

Source: (StackOverflow)

How can I call the viewmodel's method with data of the control in DOTVVM?

I have .dotcontrol and I need to call function in viewmodel with data from control.

The method cannot be in the control, because it needs facade which is available only in viewmodel. So I declared interface for viemodel and implemented this function.

But if I call it like below:

<dot:Button Click="{controlCommand: ViewModelFunction(ControlProperty)}" Text="CHECK CODE"/> 

it causes the following error:

The Name 'ViewModelFunction' does not exist in the current context'.

So I tried call it just with command:

<dot:Button Click="{command: ViewModelFunction(ControlProperty)}" Text="CHECK CODE"/>

This looked fine, but if I have two controls on one page, it doesn't work. Because the method is called with data of first usage of control. Data of another usage of the control is not recognized.

How can I call the viewmodel's method with data of the control?

Source: (StackOverflow)

Combine ASP.NET WebForms with DotVVM in single project [closed]

currently I have the web application using Web.Forms. It consist of more than thousand pages and rewriting everything from scratch will be extremely time consuming. I'm planning to gradually rewrite each page while the others remains as webforms.

Is that even possible? Having mix of DotVVM and Web.Forms pages within single project?

What would you suggest to start with? Ideally I'd like users not to even know that the page looks different. I don't care about URLs as it's admin application.

From what I learned so far I need to duplicate my current MasterPage to the .dotmaster page and then add views for pages I am rewriting.

Thanks for suggestions.

Source: (StackOverflow)

Loading subcategories in TreeView on click Dotvvm

I use business pack treeview component for menu. My goal is to retrieve only top level menu without subcategories. Subcategories will show only on user icon click (+ / - icons) or on menu item click.

So basically when I click on "a" or icon binded to this menu object, I want to send request to my server to get his subcategories and so on. I dont want to get everything in one request.

enter image description here

As I noticed there are two click handlers in view.

1) Use Changedproperty - when I use this property to handle click events, I successfully get correct object into my CategorySelectedList, but it only register clicks directly on text label. For icon it doesnt work anymore and also category menu will not expand.

2) Use Events.Clickproperty - when I use this property to handle click events. I dont even get correct object into my CategorySelectedList property, but category menu will expand in this case.

I cant send object Id from my view into SetActiveMenuNode method so I have to take it directly from my CategorySelectedList but each aproach has his own problems.

Is there any solution for this?


public List<CategoryListDTO> AdminMenuList { get; set; } = new List<CategoryListDTO>();
public List<CategoryListDTO> AdminMenuSelectedList { get; set; } = new List<CategoryListDTO>();
public void SetActiveMenuNode()
    var selected = AdminMenuSelectedList.FirstOrDefault();

//načítání podkategorií 
public StaticCommandBindingExpression LoadChildren { get; set; } = new StaticCommandBindingExpression(new CompiledBindingExpression( //something here));  

My view

<dot:Content ContentPlaceHolderID="MainContent">
<section class="content">
    <bp:TreeView DataSource="{value: AdminMenuList}"
                 SelectedValues="{value: AdminMenuSelectedList}"
                 ItemKeyBinding="{value: Id}"
                 ItemHasChildrenBinding="{value: HasCategories}"
                 ItemChildrenBinding="{value: AssignedToCategory}"
                 LoadChildren="{staticCommand: _parent.MyMethod()}"
                 Changed="{command: SetActiveMenuNode()}"          
        <p>{{value: Name}}</p>

Source: (StackOverflow)

Business pack treeview dotvvm - all tree nodes collapse after redirect

I use business pack treeview component for menu. What I want to archieve is that when I click on item Chleba for example, it will redirect me to details of this category and also items Potraviny and Pečivo should be expanded. Both items must have this css class bp-state-expanded. Right now when I am redirected to details, all items from treeview are collapsed

Below is sample of my category menu.

enter image description here

CategoryList contains all categories which are displayed in treeview.

CategorySelectedList contains single object where I clicked.

public List<CategoryListDTO> CategoryList { get; set; } = new List<CategoryListDTO>();
public List<CategoryListDTO> CategorySelectedList { get; set; } = new List<CategoryListDTO>();

Here is my redirect method to details

public void RedirectToCategory()
    var details = CategorySelectedList.FirstOrDefault();
    var productId = details.Id;
    var productCategory = details.Name;
    Context.RedirectToRoute(Routes.Product, new { ProductCategory = productCategory, Id = productId });

Is there a way how I can archieve this?

Source: (StackOverflow)

Dotvvm - fire custom binding handler after DOM elements are rendered

Lets say I want to customize css classes of treeview component.

HTML code for <li> expand. As we can see, 1st <li> got class bp-state-expanded. When its collapsed, I would like to have bp-class-collapsed class instead of bp-state-expanded for my styling purpose.

<li class="bp-item bp-state-focused bp-state-expanded" data-bind="css: $bpControl.getItemStyle($data)">
    <!-- ko if: HasCategories -->
    <a role="button" class="bp-expand">
    <i class="bp-icon fa fa-plus-square-o"></i></a>
    <a role="button" class="bp-collapse"><i class="bp-icon fa fa-minus-square-o"></i></a><!-- /ko --><label>
        <!-- ko if: $bpControl.canBeChecked($data) --><!-- /ko -->
        <i class="fa fa-circle-o"></i>
        <span><!-- ko text: Name -->Jazyky<!-- /ko --></span>
    </label><!-- ko template: { name: $findTemplateId("levelTemplate"), data: (AssignedToMenuItem) } --><!-- ko if: $data && $data.length -->
    <ul class="bp-list" data-bind="foreach: $data">

    </ul><!-- /ko --><!-- /ko -->

For my testing purpose I made this simple script where I want to store children DOM elements into variable. When I refresh page and my script is fired, treeview elements are not yet rendered.

I tried to use afterRender in data-binding but without any success. Is there a way how I can fire this handler after all DOM elements are rendered so i can manipulate with css classes?

ko.bindingHandlers["test"] = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

    var data = bindingContext.$data.AdminMenuList();
    var parentDOM = element.children;
    ko.utils.arrayForEach(data, function (item) {
        if (item().HasCategories() == true){

My data-binding in business pack treeview

<bp:TreeView DataSource="{value: AdminMenuList}"
         SelectedValues="{value: AdminMenuSelectedList}"
         ItemKeyBinding="{value: Id}"
         ItemHasChildrenBinding="{value: HasCategories}"
         ItemChildrenBinding="{value: AssignedToMenuItem}"
         Changed="{command: RedirectTo()}"
         data-bind="test: {afterRender: test }">
<i class="fa fa-circle-o"></i>
<span>{{value: Name}}</span>


For now I solved that using timeout function, but not sure if this is good aproach.

enter image description here

I got 3 types of li. I will try to explain each type.

Type 1. => Its expandable element and the reason why I need bp-class-collapsed is that, because I dont want to influence li type 2,3 with :not selector and I need here + icon.

Type 2. => Its classic li with redirect so i need o icon here. If I will use :not selector here, it will influence also this type.

Type 3. => Same as type 2, but its nested li.

I hope its better explained on this sample.

Source: (StackOverflow)

DotVVM code only component dont generate HTML structure correctly

I have my own component for treeview menu and I want to generate HTML structure like this.

<a href>
    <span class="something">
        <i class="icon"></i>

Here is my code where I generate structure for my menu

public void DataBindItem(DotvvmControl parent, AdminMenuListDTO item, IDotvvmRequestContext context)
        var li = new HtmlGenericControl("li");

        if (item.HasCategories)
            //holder pro ikonu (šipku ukazující možnost rozbalení menu)
            var iClassContainer = new HtmlGenericControl("span");
            iClassContainer.Attributes.Add("class", "pull-right-container");

            //ikona pro šipku ukazující možnost rozbalení menu
            var iClass = new HtmlGenericControl("i");
            iClass.Attributes.Add("class", "fa fa-angle-left pull-right");

            li.Attributes.Add("class", "treeview expandable");
            if (!string.IsNullOrEmpty(item.Name))
                var ahref = new HtmlGenericControl("a");
                ahref.InnerText = item.Name;
                ahref.Attributes.Add("class", "tree-toggler nav-header");
                ahref.Attributes.Add("id", item.Id.ToString());

                // add <a href> to <li> 

                // add <span> container to <a href> 

                // add <i class> to <span> which contains icon 

            var childContainer = new HtmlGenericControl("ul");
            childContainer.Attributes.Add("class", "nav nav-list tree");
            childContainer.Attributes.Add("style", "display:none;");

            foreach (var child in item.AssignedToMenuItem)
                DataBindItem(childContainer, child, context);

            li.Attributes.Add("style", "treeview");
            if (item.RouteName != null)
                var routeLink = new RouteLink();
                routeLink.RouteName = item.RouteName;
                routeLink.Text = item.Name;
                routeLink.Attributes.Add("class", "js_isRoute_" + item.Id.ToString());
                routeLink.Attributes.Add("id", item.Id.ToString());

Problem is my whole structure is not rendered in my view, I only see this. My <a href> tag should also contains span and i.

enter image description here

My structre is not rendered correctly but in debug mode in vs in my component I see it generated correctly. What I do wrong?

enter image description here

Source: (StackOverflow)

DotVVM - Code only component DataSource property is null when collection is passed in

I have my own Accordion code-only component

Here is my view where I have repeater which loads list of article sections. Each article section have list of articles. So with that I want to archieve that every article section will have his own accordion, which will contain articles. Thats why I have it in repeater

<div class="box box-primary">
    <dot:Repeater DataSource="{{value: AccordionList}}">
            <coc:Accordion DataSource="{{value: Articles}}"></coc:Accordion>

Accordion code-only component. My DataSource is always null even when I clearly see, that AccordionList contains List of Articles which is never null, but is never passed into my DataSource. When I change type of AccordionList to ArticleListDTOand pass it directly into my Accordion component, it worked well, but thats not what I want.

public class Accordion : HtmlGenericControl
    public Accordion() : base("div")
    public static readonly DotvvmProperty DataSourceProperty;
    static Accordion()
           DataSourceProperty = DotvvmProperty.Register<List<ArticleListDTO>, Accordion>(c=>c.DataSource); 
    //DataSource is always null
    public List<ArticleListDTO> DataSource
        get => (List<ArticleListDTO>)GetValue(DataSourceProperty);
        set => SetValue(DataSourceProperty, value);

    protected override void AddAttributesToRender(IHtmlWriter writer, IDotvvmRequestContext context)
        Attributes.Add("class", "accordion");

        base.AddAttributesToRender(writer, context);

    public void DataBind(IDotvvmRequestContext context)
        foreach (var item in DataSource)
            DataBindItem(this, item, context);


public List<ArticleSectionListDTO> AccordionList { get; set; } = new List<ArticleSectionListDTO>();
public List<ArticleSectionListDTO> AccordionListUnsorted { get; set; } = new List<ArticleSectionListDTO>();

protected override void OnItemLoading()
    AccordionListUnsorted = Task.Run(() => articleSectionFacade.GetAllNotModifiedArticleSections()).Result;

    AccordionList = Task.Run(() => articleSectionFacade.CreateTree(AccordionListUnsorted, null)).Result.ToList();

DTOs - I deleted rest of properties to make it clear

public class ArticleListDTO
    public string Name { get; set; }

    public int? ParentArticleId { get; set; }
    public bool HasCategories => AssignedToArticle?.Count > 0;
    public List<ArticleListDTO> AssignedToArticle { get; set; }
    //Can contain sub articles
    public List<ArticleListDTO> Articles { get; set; } = new List<ArticleListDTO>();

public class ArticleSectionListDTO : ListDTO
    public string Name { get; set; }

    public int? ParentArticleSectionId { get; set; }
    public bool HasCategories => AssignedToMenuItem?.Count > 0;
    public List<ArticleSectionListDTO> AssignedToMenuItem { get; set; }
    public List<ArticleListDTO> Articles { get; set; } = new List<ArticleListDTO>();

Source: (StackOverflow)

DotVVM - Multiselect content is overlayed by input

I have a problem with DotVVM multiselect styling. Content of multiselect is overlayed by input and I dont know what cause this problem. When I use dropdown list which uses exactly the same css classes, there isn't any problem with this. You can see dropdown list structure in picture below

Here is my HTML structure

<div class="form-group">
        <dot:Literal Text="{{value: Article.Article_Sections}}" />
    <div class="input-group">
        <bp:MultiSelect DataSource="{value: ArticleSectionsList}"
                        SelectedValues="{value: SelectedArticleSections}"
                        ItemTextBinding="{{value: Name}}"
                        ItemKeyBinding="{{value: Id}}"
                        class="form-control " />
<div class="form-group">
        <dot:Literal Text="{{value: DetailDTO.Name}}" />
    <div class="input-group" Validator.Value="{{value: DetailDTO.Name}}">
        <dot:TextBox class="form-control" Text="{{value: DetailDTO.Name}}" />


CSS code here

.form-group {
    position: relative;

.input-group {
    position: relative;
    display: table;
    border-collapse: separate;

.dotvvm-bp-multi-select .bp-popup {
    display: none;
    padding: 5px 2px;
    position: fixed;
    overflow: hidden;
    border-collapse: collapse;
    border: 1px solid #808080;
    border-radius: 0;
    background-color: #fff;
    color: #1a1a1a;
    font-weight: normal;
    cursor: default;
    margin-top: 1px;
    z-index: 1001;
    text-align: left;
//here is css for opened state
.dotvvm-bp-multi-select .bp-popup.bp-state-opened {
    display: block;
    z-index: 1001;

.dotvvm-bp-multi-select .bp-popup.bp-has-list > ul {
    list-style: none;
    overflow-x: hidden;
    padding: 5px 2px;
    max-height: 250px;
    margin: 0;

Image is edited, I changed dropdown list to simple text input in my previous code structure to make it more readable, problem is still the same. enter image description here

Image showing dropdown list component, which works fine

enter image description here

Source: (StackOverflow)

DotVVM Authentication

I've encountered a problem with Owin Authentication in dotVVM framework. I get 401 error after authorization on page that requires to be authenticated.

This is my current startup.cs

var applicationPhysicalPath = HostingEnvironment.ApplicationPhysicalPath;

// use DotVVM
DotvvmConfiguration dotvvmConfiguration = app.UseDotVVM(applicationPhysicalPath);
dotvvmConfiguration.RouteTable.Add("Login", "", "Views/login.dothtml", null);
dotvvmConfiguration.RouteTable.Add("Home", "Home", "Views/home.dothtml", null);
dotvvmConfiguration.RouteTable.Add("Register", "Register", "Views/register.dothtml", null);

// use static files
app.UseStaticFiles(new StaticFileOptions()
    FileSystem = new PhysicalFileSystem(applicationPhysicalPath)

app.UseCookieAuthentication(new CookieAuthenticationOptions()
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie


public class HomeViewModel : DotvvmViewModelBase { }

I've created Auth Cookie this way

public void Login()
    var identity = LoginHelper.GetIdentity(Email, DataAccess.DbAccess.CreateHash(Password));
    if (identity == null)

    Context.OwinContext.Authentication.SignIn(new ClaimsIdentity(identity));

Source: (StackOverflow)

Add trigger/commit character to VisualStudio Html Completion

I am trying to create extension for framework in which combination of html markup and custom experessions is used. I would like to trigger and commit completion session for those experessions. Is there any easy way to add custom characters to trigger and commit completion session inside html editor in VisualStudio? I know that there is this "I implement custom CompletionCommand" way of doing it. My problem is I need to combine standard html completions on html markup but I need to add support for characters that start my custom expresions completion. So I thought it would be easier to make use of something HtmlCompletionSession already has.

Source: (StackOverflow)

Problems with Bootstrap DotVVM GridView

I have the following code in a bootstrap table:

<bs:GridView DataSource="{value: TablaGridView}" SortChanged="{command: OrdenaTabla}" class="table table-striped table-bordered table-hover table-full-width">
        <dot:GridViewTextColumn HeaderText="Nombre" ValueBinding="{value: Nombre}" AllowSorting="True" />
        <dot:GridViewTextColumn HeaderText="Apellido Paterno" ValueBinding="{value: ApellidoPaterno}" AllowSorting="True" />
        <dot:GridViewTextColumn HeaderText="Apellido Materno" ValueBinding="{value: ApellidoMaterno}" AllowSorting="True" />
        <dot:GridViewTextColumn HeaderText="Estado" ValueBinding="{value: Estado}" AllowSorting="True" />
        <dot:GridViewTextColumn HeaderText="RFC" ValueBinding="{value: RFC}" AllowSorting="True" />
        <dot:GridViewTemplateColumn AllowSorting="false">
                <dot:Button ButtonTagName="button" class="btn btn-blue show-sv" rel='nofollow' href="#FormaCliente" data-startFrom="right" Click="{command: _parent.Edit(_this)}">
                    <i class="fa fa-edit"></i> Editar
                <dot:Button ButtonTagName="button" class="btn btn-red" Click="{command: _parent.Delete(_this)}">
                    <i class="fa fa-trash-o"></i> Borrar

In the template I have two buttons, which will open a form to edit the data in the table. But I have the problem that the button did not perform the action inside the grid. If I put the button outside the grid performs the action, however inside the grid does nothing. You could help me solve this situation.



This is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotVVM.Framework.ViewModel;
using System.Threading.Tasks;
using DotVVM.Framework.Controls.Bootstrap;
using DotVVM.Framework.Controls;

namespace APP_POS.ViewModels
    public class TablaViewModel : DotvvmViewModelBase

        private static IQueryable<CustomerData> GetData()
            return new[]
                new CustomerData() { Id = 1, Nombre = "John Doe", RFC = DateTime.Parse("1976-04-01") },
                new CustomerData() { Id = 2, Nombre = "John Deer", RFC = DateTime.Parse("1984-03-02")},
                new CustomerData() { Id = 3, Nombre = "Johnny Walker", RFC = DateTime.Parse("1934-01-03")},
                new CustomerData() { Id = 4, Nombre = "Jim Hacker", RFC = DateTime.Parse("1912-11-04")},
                new CustomerData() { Id = 5, Nombre = "Joe E. Brown", RFC = DateTime.Parse("1947-09-05")},
                new CustomerData() { Id = 6, Nombre = "Jim Harris", RFC = DateTime.Parse("1956-07-06") },
                new CustomerData() { Id = 7, Nombre = "J. P. Morgan", RFC = DateTime.Parse("1969-05-07")},
                new CustomerData() { Id = 8, Nombre = "J. R. Ewing", RFC = DateTime.Parse("1987-03-08")},
                new CustomerData() { Id = 9, Nombre = "Jeremy Clarkson", RFC = DateTime.Parse("1994-04-09") },
                new CustomerData() { Id = 10, Nombre = "Jenny Green", RFC = DateTime.Parse("1947-02-10")},
                new CustomerData() { Id = 11, Nombre = "Joseph Blue", RFC = DateTime.Parse("1948-12-11")},
                new CustomerData() { Id = 12, Nombre = "Jack Daniels", RFC = DateTime.Parse("1968-10-12")},
                new CustomerData() { Id = 13, Nombre = "Jackie Chan", RFC = DateTime.Parse("1978-08-13")},
                new CustomerData() { Id = 14, Nombre = "Jasper", RFC = DateTime.Parse("1934-06-14")},
                new CustomerData() { Id = 15, Nombre = "Jumbo", RFC = DateTime.Parse("1965-06-15")},
                new CustomerData() { Id = 16, Nombre = "Junkie Doodle", RFC = DateTime.Parse("1977-05-16")}

        public GridViewDataSet<CustomerData> Customers { get; set; }

        public string SelectedSortColumn { get; set; }

        public TablaViewModel()
            // creates new GridViewDataSet and sets PageSize
            Customers = new GridViewDataSet<CustomerData>();
            Customers.PageSize = 10;

        public void Edit(CustomerData customer)
            Customers.EditRowId = customer.Id;

        public void Delete(CustomerData customer)
            Customers.EditRowId = customer.Id;

        public override Task PreRender()
            // fill customers
            if (SelectedSortColumn == "Nombre")
                Customers.LoadFromQueryable(GetData().OrderBy(c => c.Nombre));
            else if (SelectedSortColumn == "RFC")
                Customers.LoadFromQueryable(GetData().OrderBy(c => c.RFC));


            return base.PreRender();

        public void SortCustomers(string column)
            SelectedSortColumn = column;


    public class CustomerData
        public int Id { get; set; }

        public string Nombre { get; set; }

        public DateTime RFC { get; set; }



Source: (StackOverflow)