DEV Community

Kashif Soofi
Kashif Soofi

Posted on

GTK4 ColumnView with .NET 8

In this post I will make use of ColumnView to display list of data. ColumnView is used to display 1-dimensional list with one or more columns. Foucus of this post will be to dispaly multiple columns.

Project Setup

Let's start by setting up a new solution and project.

dotnet new sln --name ColumnView
dotnet new console -o ColumnView.App
dotnet sln add ColumnView.App/ColumnView.App.csproj
Enter fullscreen mode Exit fullscreen mode

And add a reference to GirCore.Gtk-4.0 nuget package, the latest version is 0.5.0-preview.4 at the time of writing.

cd ColumnView.App
dotnet add package GirCore.Gtk-4.0 --version 0.5.0-preview.4
Enter fullscreen mode Exit fullscreen mode

ColumnViewWindow

I will add a new class named ColumnViewWindow inheriting from Gtk.Window. This window will contain a ColumnView widget to display tabular data.

Model

First let's add a class that we will use to display our data and a static method to generate the sample data. We will inherit this model from GObject.Object.

public class UserData : GObject.Object
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }

    public UserData(int id, string firstName, string lastName, string username, string email)
        : base(true, Array.Empty<GObject.ConstructArgument>())
    {
        Id = id;
        FirstName = firstName;
        LastName = lastName;
        Username = username;
        Email = email;
    }

    public static UserData[] SampleUserData()
    {
        return
        [
            new UserData(1, "Leanne", "Graham", "Bret", "Sincere@april.biz"),
            new UserData(2, "Ervin", "Howell", "Antonette", "Shanna@melissa.tv"),
            new UserData(3, "Patricia", "Lebsack", "Karianne", "Julianne.OConner@kory.org"),
            new UserData(4, "Chelsey", "Dietrich", "Kamren", "Lucio_Hettinger@annie.ca"),
            new UserData(5, "Clementine", "Bauch", "Samantha", "Nathan@yesenia.net"),
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

ColumnViewWindow

Next let's update the ColumnViewWindow to inherit from Gtk.Window. And then initialise ListStore and widgets to display the data.

First we will add a Gio.ListStore and add our sample data to the list store. Then we will add a single seletion model using the model.

var model = Gio.ListStore.New(UserData.GetGType());
foreach (var userData in UserData.SampleUserData())
{
    model.Append(userData);
}

var selectionModel = SingleSelection.New(model);
selectionModel.Autoselect = false;
selectionModel.CanUnselect = true;
Enter fullscreen mode Exit fullscreen mode

Next we will add ColumnView and add it to a ScrolledWindow and add the scrolled window widget to ColumnViewWindow.

var columnView = ColumnView.New(selectionModel);
columnView.AddCssClass("data-table");

var scrolledWindow = ScrolledWindow.New();
scrolledWindow.Child = columnView;

Child = scrolledWindow;
Enter fullscreen mode Exit fullscreen mode

Text Columns

Next we will add text based columns displaying data using Label widget.

// Id Column
var listItemFactory = SignalListItemFactory.New();
listItemFactory.OnSetup += (_, args) => OnSetupLabel(args, Align.End);
listItemFactory.OnBind += (_, args) => OnBindText(args, (ud) => ud.Id.ToString());

var idColumn = ColumnViewColumn.New(nameof(UserData.Id), listItemFactory);
columnView.AppendColumn(idColumn);

// Name Column
listItemFactory = SignalListItemFactory.New();
listItemFactory.OnSetup += (_, args) => OnSetupLabel(args, Align.Start);
listItemFactory.OnBind += (_, args) => OnBindText(args, (ud) => ud.Name);

var nameColumn = ColumnViewColumn.New(nameof(UserData.Name), listItemFactory);
columnView.AppendColumn(nameColumn);

// Sales Column
listItemFactory = SignalListItemFactory.New();
listItemFactory.OnSetup += (_, args) => OnSetupLabel(args, Align.End);
listItemFactory.OnBind += (_, args) => OnBindText(args, (ud) => $"{ud.Sales:C}");

var salesColumn = ColumnViewColumn.New(nameof(UserData.Sales), listItemFactory);
columnView.AppendColumn(salesColumn);
Enter fullscreen mode Exit fullscreen mode

I have added helper methods to OnSetupLabel and OnBindText to reuse code to create Label and set text when binding data.

private void OnSetupLabel(SetupSignalArgs args, Align align)
{
    if (args.Object is not ListItem listItem)
    {
        return;
    }

    var label = Label.New(null);
    label.Halign = align;
    listItem.Child = label;
}

private void OnBindText(BindSignalArgs args, Func<UserData, string> getText)
{
    if (args.Object is not ListItem listItem)
    {
        return;
    }

    if (listItem.Child is not Label label) return;
    if (listItem.Item is not UserData userData) return;

    label.SetText(getText(userData));
}
Enter fullscreen mode Exit fullscreen mode

ProgressBar Column

This is just to display how to use the ProgressBar widget and also to demonstrate that any widget can be used in the ColumnView.

Code to add the column

// Percentage Column
listItemFactory = SignalListItemFactory.New();
listItemFactory.OnSetup += OnSetupProgress;
listItemFactory.OnBind += OnBindProgress;

var percentageColumn = ColumnViewColumn.New(nameof(UserData.ProgressPercentage), listItemFactory);
columnView.AppendColumn(percentageColumn);
Enter fullscreen mode Exit fullscreen mode

And methods to create widget and set data

private void OnSetupProgress(SignalListItemFactory sender, SetupSignalArgs args)
{
    if (args.Object is not ListItem listItem)
    {
        return;
    }

    var progressBar = ProgressBar.New();
    progressBar.SetShowText(true);
    listItem.Child = progressBar;
}

private void OnBindProgress(SignalListItemFactory sender, BindSignalArgs args)
{
    if (args.Object is not ListItem listItem)
    {
        return;
    }

    if (listItem.Child is not ProgressBar progressBar) return;
    if (listItem.Item is not UserData userData) return;

    progressBar.SetFraction(userData.ProgressPercentage * 0.01);
}
Enter fullscreen mode Exit fullscreen mode

Program.cs

Lets update Program.cs to create and show our ColumnViewWindow.

var application = Gtk.Application.New("org.kashif-code-samples.columnview.sample", Gio.ApplicationFlags.FlagsNone);
application.OnActivate += (sender, args) =>
{
    var window = new ColumnViewWindow
    {
        Application = application
    };
    window.Show();
};
return application.RunWithSynchronizationContext(null);
Enter fullscreen mode Exit fullscreen mode

Running the program will show us following window.

Column View Window

Source

Source code for the sample application is available on GitHub in gtk4-dotnet8-column-view.

References

In no particular order

Top comments (0)