---
title: "UNO Platform - Build a Todo App - Part 4"
description: "In the forth part we will take care of our newly created todo item. Until now we clicked on a button and that's all. Sure we have a nice form where we can enter the basic information, but that is all.\n\nThe time has come to put our element into the respective swimlane. We will also learn how to add further nuget packages to our project."
updated: 2022-03-23
tags: ["C#", "UNO Platform"]
canonical: "https://steven-giesel.com/blogPost/2d96d970-ef11-48f4-a102-9339fc362a75/uno-platform-build-a-todo-app-part-4"
---

# UNO Platform - Build a Todo App - Part 4

Welcome back to our series: How to create a todo app with the **Uno platform**.
As a small recap we created in the last part of the series a nice form which also validates our model. That looked fancy but that was the end of the show. We will start exactly from there and add the element into the right swimlane.

A small teaser where we are going:

![Result](https://linkdotnetblog.azureedge.net/blog/20220323_UnoPart4/Result.gif)

## Return the item
Our dialog was capable of creating the todo item and only allows the user the press "Add" when the model is in a valid state. You might be surprised but we are done with the dialog itself. As we attached the viewmodel to the `DataContext` of our dialog, we can use this from our button. Remember the press on the red button opened the dialog. So here is our next stop:

```csharp
public event EventHandler<Todo> TodoItemCreated;

private void OpenDialog(object sender, RoutedEventArgs args)
{
    var dialog = new AddTodoItemDialog();

    // We will hook into the PrimaryButtonClick here
    dialog.PrimaryButtonClick += (s, a) => NewTodoItemCreated((NewTodoItemViewModel)dialog.DataContext);
    dialog.ShowAsync();
}

private void NewTodoItemCreated(NewTodoItemViewModel viewModel)
{
    var todo = new Todo
    {
        Description = viewModel.Description,
        Title = viewModel.Title,
        DueDate = viewModel.DueDate.DateTime,
        KanbanState = KanbanState.New,
    };

    TodoItemCreated?.Invoke(this, todo);
}
```

The idea is simple:
 * Attach to the `PrimaryButtonClick` which in fact is our *Add* button
 * Create our domain object from the view model and raise the newly created `TodoItemCreated` with that item

Now the parent is responsible to subscribe to `TodoItemCreated`-event and do something with it. The parent of our button is the `MainPage` itself. So it will be time to do some work here.

## MainPage.xaml
### View Model
Before we do anything we the event, we need some kind of storage. We will use a newly created view model to do so. Our ViewModel is fairly simple:

MainPageViewModel.cs
```csharp
using MvvmHelpers;
using TodoApp.Domain;

namespace TodoApp
{
    public class MainPageViewModel : ObservableObject
    {
        private ObservableRangeCollection<Todo> todoItems = new ObservableRangeCollection<Todo>();

        public ObservableRangeCollection<Todo> TodoItems
        {
            get => todoItems;
            set
            {
                todoItems = value;
                OnPropertyChanged();
            }
        }
    }
}
```

We just have an `ObservableCollection` which holds all of our `Todo` items. The `ObservableCollection` has the advantage that it works nicely with the **Uno Platform** (like in WPF or UWP). So everytime we add an element, all the bindings get notified so we don't have to do this in our own.
Now that we have some kind of state, we can hook into the event from our button and add the element to the list.

### Put the item into our view model
As with all C# events we just attach ourselves in the code behind and add the newly created item to our view model:

MainPage.xaml.cs
```csharp
public sealed partial class MainPage : Page
{
    public MainPage()
    {
        InitializeComponent();
        DataContext = new MainPageViewModel();
        addItemButton.TodoItemCreated += (o, item) => ((MainPageViewModel)DataContext).TodoItems.Add(item);
    }
}
```

Before we continue one important fact which we will leverage next: `DataContext` gets automatically inherited by child components if not overwritten. That means that our `Swimlane` automatically has now **all** the Todo items even though we never explicitly declared this. In this tutorial I will use that fact and don't create a separate view model for the `Swimlane`. 

## Adding it to the `Swimlane`
As described above, we are already added this new item indirectly to our `Swimlane` as the `Swimlane` inherits the `DataContext` from the `MainPage`. 
Let's just add some content to the `Swimlane`. We already started a bit, but in theory nothing is shown. So we will extend our `<ListView.ItemTemplate>`. Also we will set the `ListView.ItemContainerStyle` to use the whole width of the `StackPanel`.

Swimlane.xaml

```xml
<UserControl
    x:Class="TodoApp.Swimlane"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TodoApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <StackPanel MinWidth="200" MinHeight="400" BorderBrush="DarkOliveGreen" BorderThickness="2">
        <TextBlock Text="{x:Bind State}" HorizontalAlignment="Center"></TextBlock>
        <ListView x:Name="itemListView" HorizontalContentAlignment="Stretch">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:TodoItem></local:TodoItem>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackPanel>
</UserControl>
```

Hupps, there is now something missing: The `TodoItem` user control. For now we will hold it very simple. We just show all the properties we have in a `StackPanel`. Therefore create a new **Uno Platform User Control**:

TodoItem.xaml
```xml
<UserControl
    x:Class="TodoApp.TodoItem"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TodoApp"
    xmlns:domain="using:TodoApp.Domain"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DataContext="{d:DesignInstance Type=domain:Todo}"
    d:DesignHeight="300"
    d:DesignWidth="400">
    <StackPanel>
        <TextBlock Text="{Binding Path=Title}" TextAlignment="Center" FontWeight="Bold"></TextBlock>
        <TextBlock Text="{Binding Path=Description}" Margin="0,10,0,0"></TextBlock>
        <TextBlock Text="{Binding Path=DueDate}" Margin="0,10,0,0"></TextBlock>
    </StackPanel>
</UserControl>
```

Also here we will use the `DataContext`. The `DataContext` from the point of view of our `TodoItem` is not the `ObservableCollection` anymore but one single `TodoItem`. Perfect! By the way with: `d:DataContext="{d:DesignInstance Type=domain:Todo}"` you can help IntelliSense to show you the right properties.

Looks like we are done, or? Let's hit the compiler and look what we have created:

![AllLanes](https://linkdotnetblog.azureedge.net/blog/20220323_UnoPart4/AllLanes.JPG)

Hmmm we don't want to have that single `Todo` item in all of our lanes. One `Swimlane` is responsible for one `KanbanState`.
The thing is all of our swimlane see the same content. Until now they don't know how to filter anything.

## Filter the swimlanes
To filter our `Swimlane`s according to the previous set state we will leverage a nice component: [`AdvancedCollectionView`](https://docs.microsoft.com/en-us/windows/communitytoolkit/helpers/advancedcollectionview). The `AdvancedCollectionView` is part of the Community Toolkit.

Now the very cool thing with the **Uno Platform** is that they ported the community toolkit. If you want to know more go [here](https://platform.uno/docs/articles/uno-community-toolkit.html?tabs=tabid-vswin). I will just briefly summarize and guide you through with the most important points.

For our case we need to add the `Uno.Microsoft.Toolkit.Uwp.UI` nuget package, **but**:
 * Only add the `Uno.Microsoft.Toolkit.Uwp.UI` to every production project **besides** the **UWP** or **WinUI3** head
 * For **UWP** or **WinUI3** head use `Microsoft.Toolkit.Uwp.UI`
 * Keep the versions aligned. In my case both packages have version `7.1.1`.
 * *Uno platform** is totally aligned with the name of the packages. They just prefixed it with **Uno**
 * The namespaces are also the same

Now that we added the package(s). We can use the `AdvancedCollectionView`.
For that we go into `Swimlane.xaml.cs`:

```csharp
public Swimlane()
{
    InitializeComponent();
    DataContextChanged += SetFilter;
}

private void SetFilter(FrameworkElement sender, DataContextChangedEventArgs args)
{
    var view = new AdvancedCollectionView(((MainPageViewModel)this.DataContext).TodoItems, true);
    view.Filter = item => ((Todo)item).KanbanState == State;
    itemListView.ItemsSource = view;
}
```
Now what are we doing here. Once the `DataContext` is loaded or changed (via `DataContextChanged`) we apply our `Filter` method. We already introduced the `State` in an eariler episode of the series (to use it in the header). Last but not least we set the `ItemsSource` of our `ListView` to the newly created and filtered `AdvancedCollectionView`. Very straight forward!. Now if you compile again and run the application you see the image as shown at the beginning:

![Result](https://linkdotnetblog.azureedge.net/blog/20220323_UnoPart4/Result.gif)

Something which bugged me was that the "default" date for our `NewTodoItemViewModel` is basically `default(DateTimeOffset)` which is 1922. We can easily address this via: `private DateTimeOffset dueDate = DateTimeOffset.Now;`.

And there you go. We added our todo item into the right column and also did the ground work for further adjustments.

## Resources
 * [Part 1](https://steven-giesel.com/blogPost/b2234ada-0978-4c7b-841e-ca6a255247b0) of the series
 * [Part 2](https://steven-giesel.com/blogPost/85814db0-3495-492c-8ce1-5c83d708590b) of the series
 * [Part 3](https://steven-giesel.com/blogPost/a3179d55-d5be-48ba-b570-ee7d494a8b21) of the series
 * [Part 5](https://steven-giesel.com/blogPost/2c025ac6-d67f-45ec-a616-009e0285c999) of the series
 * The github repository for this Todo-App: [here](https://github.com/linkdotnet/BlogExamples/tree/main/TodoApp)
 * Official UNO Platform website: [here](https://platform.uno/)