Search code examples
c#wpfdata-binding

How to use a converter for a texblock of a calendar?


I am trying to add a new column in a calendar control to add the week number. I have found a example that works perfect, the problem is very simply and it uses code behind, and I am wanted to use MVVM and a converter in another class, no inside the code behind.

Then example that I have found is this:

<Window x:Class="CalendarioNumeroSemana.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:CalendarioNumeroSemana"
        xmlns:app="clr-namespace:CalendarioNumeroSemana"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Calendar Grid.IsSharedSizeScope="True" HorizontalAlignment="Left" Margin="209,116,0,0" VerticalAlignment="Top">
            <Calendar.CalendarDayButtonStyle>
                <Style TargetType="{x:Type CalendarDayButton}">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding Path=(Grid.Column),RelativeSource={RelativeSource Mode=Self}}" 
                                     Value="0">
                            <Setter Property="ContentTemplate">
                                <Setter.Value>
                                    <DataTemplate>
                                        <Grid HorizontalAlignment="Right">
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition SharedSizeGroup="XX"/>
                                                <ColumnDefinition SharedSizeGroup="YY"/>
                                            </Grid.ColumnDefinitions>
                                            <Border  BorderThickness="0,0,0,0" BorderBrush="Black" Margin="-15,0,0,0">
                                                <TextBlock  Margin="0,0,2,0" FontWeight="Bold">
                                                    <TextBlock.Text>
                                                        <Binding Path="DataContext">
                                                            <Binding.Converter>
                                                                <app:WeekNumberConverter />
                                                            </Binding.Converter>
                                                            <Binding.RelativeSource>
                                                                <RelativeSource Mode="FindAncestor"
                                                                                AncestorType="{x:Type CalendarDayButton}"/>
                                                            </Binding.RelativeSource>
                                                        </Binding>
                                                    </TextBlock.Text>
                                                </TextBlock>
                                            </Border>
                                            <TextBlock Text="{Binding }" Grid.Column="1" HorizontalAlignment="Center"/>
                                        </Grid>
                                    </DataTemplate>
                                </Setter.Value>
                            </Setter>
                        </DataTrigger>
                    </Style.Triggers>

                </Style>
            </Calendar.CalendarDayButtonStyle>
        </Calendar>

    </Grid>
</Window>



namespace CalendarioNumeroSemana
{
    /// <summary>
    /// Lógica de interacción para MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }




    public class WeekNumberConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value is DateTime)
            {
                DateTime dt = (DateTime)value;
                return getNumeroSemenaIso8601(dt);
            }
            return value;

        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }





        private int getNumeroSemenaIso8601(DateTime paramFecha)
        {
            System.Globalization.Calendar miCalendario = CultureInfo.InvariantCulture.Calendar;

            DateTime miDtFechaBase = paramFecha;

            DayOfWeek miDiaSemana = miCalendario.GetDayOfWeek(paramFecha);


            if (miDiaSemana == DayOfWeek.Monday) { miDtFechaBase = miDtFechaBase.AddDays(3); }

            if (miDiaSemana == DayOfWeek.Tuesday) { miDtFechaBase = miDtFechaBase.AddDays(2); }

            if (miDiaSemana == DayOfWeek.Wednesday) { miDtFechaBase = miDtFechaBase.AddDays(1); }

            if (miDiaSemana == DayOfWeek.Friday) { miDtFechaBase = miDtFechaBase.AddDays(-1); }

            if (miDiaSemana == DayOfWeek.Saturday) { miDtFechaBase = miDtFechaBase.AddDays(-2); }

            if (miDiaSemana == DayOfWeek.Sunday) { miDtFechaBase = miDtFechaBase.AddDays(-3); }


            return miCalendario.GetWeekOfYear(miDtFechaBase, CalendarWeekRule.FirstFourDayWeek, DayOfWeek.Monday);
        }
    }
}

But I would like to use this in my application, that it uses MVVM and I have the converter to get the week number in another class.

My axml is this:

<Calendar Grid.IsSharedSizeScope="True" HorizontalAlignment="Left" Margin="5,5,5,5" Padding="0,0,0,0" VerticalAlignment="Top">
    <Calendar.CalendarDayButtonStyle>
        <Style TargetType="{x:Type CalendarDayButton}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=(Grid.Column),RelativeSource={RelativeSource Mode=Self}}" 
                         Value="0">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <Grid HorizontalAlignment="Right">
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition SharedSizeGroup="XX"/>
                                        <ColumnDefinition SharedSizeGroup="YY"/>
                                    </Grid.ColumnDefinitions>
                                    <Border  BorderThickness="0,0,0,0" BorderBrush="Black" Margin="-15,0,0,0">
                                        <TextBlock  Margin="0,0,2,0" FontWeight="Bold">
                                            <TextBlock.Text>
                                                <Binding Path="DataContext">
                                                    <Binding.Converter>
                                                        <app:WeekNumberConverter />
                                                    </Binding.Converter>
                                                    <Binding.RelativeSource>
                                                        <RelativeSource Mode="FindAncestor"
                                                                    AncestorType="{x:Type CalendarDayButton}"/>
                                                    </Binding.RelativeSource>
                                                </Binding>
                                            </TextBlock.Text>
                                        </TextBlock>
                                    </Border>
                                    <TextBlock Text="{Binding }" Grid.Column="1" HorizontalAlignment="Center"/>
                                </Grid>
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Calendar.CalendarDayButtonStyle>
</Calendar>

My main problem is that I don't know how to change the code of binding.text, and later, in TextBlock Text, it uses Binding, but I don't know what binding is this.

I have tried something like that:

<TextBlock.Text>
                                                            <Binding Converter="{StaticResource NumeroSemanaValueConverter}"/>
                                                        </TextBlock.Text>

But in the converter I don't get a date, I g et the day of the first button. I need the date.

So how could I adapt the original code to my case?

Thanks.


Solution

  • This has nothing to do with MVVM. It's pure control logic. The template of the control uses a converter to get the week number. A converter is just a class and a template is just a template.

    So the example you have found can certainly be used in a MVVM application. It's just a built-in control with a custom template. No view model or logic that should belong to a view model is involved as far as I can see.