therealchriswoodward
therealchriswoodward

Reputation: 49

How do I use CalendarView to filter through entries like in a journal?

I'm very much a beginner, and I don't even know where to start with the CalendarView.

What I have so far is a simple app where I type into a textbox and click a button and what I typed is appended to a txt file. Every entry has a time stamp added to it with DateTime.

What I want is to be able to click a date on the calendar view and show every entry that occurred on that day, so if there were entries all week long, and I only want to see the entries on the 21st of the month, I would click on the 21st in the calendar view and I would then see all the entries from that day in a ListView or text block or something.

I have no idea where to even start with this. Any and all help is greatly appreciated.

Upvotes: 1

Views: 238

Answers (1)

Andrew KeepCoding
Andrew KeepCoding

Reputation: 13536

You can start with something like this.

CAUTION

I'm using the CommunityToolkit.Mvvvm NuGet package to implement MVVM.

MainWindowViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace CalendarViewTest;

public record Entry(DateTimeOffset Timestamp, string Text);

// The "ObservableObject" and "ObservableProperty" 
// are from the CommunityToolkit.Mvvm NuGet package.
// It helps you implement MVVM to your app.
public partial class MainWindowViewModel : ObservableObject
{
    [ObservableProperty]
    // An UI-interactive "FilteredEntries" property will be auto-generated.
    private ObservableCollection<Entry>? filteredEntries;

    [ObservableProperty]
    // An UI-interactive "TargetDate" property will be auto-generated.
    private DateTime? targetDate;

    public MainWindowViewModel()
    {
        RefreshFilteredEntries();
    }

    private List<Entry> SourceEntries { get; } = new()
    {
        new(Timestamp: DateTime.Now, "now"),
        new(Timestamp: DateTime.Now.AddMinutes(-1), "a minute ago"),
        new(Timestamp: DateTime.Now.AddHours(-1), "an hour ago"),
        new(Timestamp: DateTime.Now.AddDays(-1), "yesterday"),
        new(Timestamp: DateTime.Now.AddDays(-2), "2 days ago"),
        new(Timestamp: DateTime.Now.AddDays(-3), "3 days ago"),
        new(Timestamp: DateTime.Now.AddMonths(-1), "a month ago"),
    };

    private void RefreshFilteredEntries()
    {
        FilteredEntries = new ObservableCollection<Entry>(SourceEntries
            .Where(x => x.Timestamp.Date == TargetDate?.Date));
    }

    // This partial method is auto-generated and will be called when "TargetDate" is changed.
    partial void OnTargetDateChanged(DateTime? value)
    {
        RefreshFilteredEntries();
    }
}

MainWindow.xaml.cs

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace CalendarViewTest;

public sealed partial class MainWindow : Window
{
    public MainWindow()
    {
        this.InitializeComponent();
    }

    public MainWindowViewModel ViewModel { get; } = new();

    private void CalendarView_SelectedDatesChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
    {
        ViewModel.TargetDate = args.AddedDates.Count > 0
            ? args.AddedDates[0].Date
            : null;
    }
}

MainWindow.xaml

<Window
    x:Class="CalendarViewTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:CalendarViewTest"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid ColumnDefinitions="Auto,*">
        <CalendarView
            Grid.Column="0"
            VerticalAlignment="Top"
            SelectedDatesChanged="CalendarView_SelectedDatesChanged"
            SelectionMode="Single" />
        <ListView
            Grid.Column="1"
            ItemsSource="{x:Bind ViewModel.FilteredEntries, Mode=OneWay}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Entry">
                    <Grid ColumnDefinitions="Auto,*">
                        <TextBlock
                            Grid.Column="0"
                            Text="{x:Bind Timestamp}" />
                        <TextBlock
                            Grid.Column="1"
                            Text="{x:Bind Text}" />
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>

</Window>

Upvotes: 2

Related Questions