0

I am trying to make a schedular control a bit like the one inside Outlook.

I know devexpress has a control in his library, but I am not willing to pay that much (every year) for this control.

Now the next thing that I need to do is actually make the grid cells clickable. Does anybody have an idea on doing that?

This is an image of the office behavior I want to create: Office Behavior

This is the code I have right now (keep in mind that I will translate this later on to a custom control that reacts dynamicly).

<Window x:Class="Ghostware.Scheduler.Example.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:Ghostware.Scheduler.Example"
        xmlns:scheduler="clr-namespace:Ghostware.Scheduler;assembly=Ghostware.Scheduler"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="800">
    <Grid IsSharedSizeScope="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <!--<scheduler:Scheduler Margin="5" />-->
        <local:BorderGrid Grid.Row="0">
            <local:BorderGrid.ColumnDefinitions>
                <ColumnDefinition Width="60" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="17" />
            </local:BorderGrid.ColumnDefinitions>
            <local:BorderGrid.RowDefinitions>
                <RowDefinition Height="22" />
                <RowDefinition MinHeight="22" />
                <RowDefinition Height="2" />
            </local:BorderGrid.RowDefinitions>

            <StackPanel Grid.Row="0" Grid.Column="1" Background="LightBlue">
                <TextBlock Text="Monday 11 July" TextAlignment="Center" />
            </StackPanel>
            <StackPanel Grid.Row="0" Grid.Column="2" Background="LightBlue">
                <TextBlock Text="12 July" TextAlignment="Center" />
            </StackPanel>
            <StackPanel Grid.Row="0" Grid.Column="3" Background="LightBlue">
                <TextBlock Text="13 July" TextAlignment="Center" />
            </StackPanel>
            <StackPanel Grid.Row="0" Grid.Column="4" Background="LightBlue">
                <TextBlock Text="14 July" TextAlignment="Center" />
            </StackPanel>
            <StackPanel Grid.Row="0" Grid.Column="5" Background="LightBlue">
                <TextBlock Text="15 July" TextAlignment="Center" />
            </StackPanel>
            <StackPanel Grid.Row="0" Grid.Column="6" Background="LightBlue"></StackPanel>

            <StackPanel Grid.Row="1" Grid.Column="1" Background="LightGray"></StackPanel>
            <StackPanel Grid.Row="1" Grid.Column="2" Background="LightGray"></StackPanel>
            <StackPanel Grid.Row="1" Grid.Column="3" Background="LightGray"></StackPanel>
            <StackPanel Grid.Row="1" Grid.Column="4" Background="LightGray"></StackPanel>
            <StackPanel Grid.Row="1" Grid.Column="5" Background="LightGray"></StackPanel>
            <StackPanel Grid.Row="1" Grid.Column="6" Background="LightGray"></StackPanel>

        </local:BorderGrid>
        <ScrollViewer Grid.Row="1">
            <local:BorderGrid>
                <local:BorderGrid.ColumnDefinitions>
                    <ColumnDefinition Width="60" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </local:BorderGrid.ColumnDefinitions>
                <local:BorderGrid.RowDefinitions>
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                    <RowDefinition Height="44" />
                </local:BorderGrid.RowDefinitions>

                <TextBlock Text="00 00" Grid.Row="1" Grid.Column="0" TextAlignment="Right" Margin="0,2,5,0" />
                <TextBlock Text="01 00" Grid.Row="3" Grid.Column="0" TextAlignment="Right" Margin="0,2,5,0" />
                <TextBlock Text="02 00" Grid.Row="5" Grid.Column="0" TextAlignment="Right" Margin="0,2,5,0" />
                <TextBlock Text="03 00" Grid.Row="7" Grid.Column="0" TextAlignment="Right" Margin="0,2,5,0" />
                <TextBlock Text="04 00" Grid.Row="9" Grid.Column="0" TextAlignment="Right" Margin="0,2,5,0" />
                <TextBlock Text="05 00" Grid.Row="11" Grid.Column="0" TextAlignment="Right" Margin="0,2,5,0" />

                <StackPanel Grid.Row="3" Grid.Column="2" Grid.RowSpan="5" Background="Red" Margin="0,0,20,0" />
            </local:BorderGrid>
        </ScrollViewer>
    </Grid>
</Window>

The bordergrid file:

public class BorderGrid : Grid
{
    protected override void OnRender(DrawingContext dc)
    {
        double leftOffset = 0;
        double topOffset = 0;
        Pen pen = new Pen(Brushes.Gray, 0.5);
        pen.Freeze();

        foreach (RowDefinition row in RowDefinitions)
        {
            dc.DrawLine(pen, new Point(0, topOffset), new Point(this.ActualWidth, topOffset));
            topOffset += row.ActualHeight;
        }

        foreach (ColumnDefinition column in ColumnDefinitions)
        {
            dc.DrawLine(pen, new Point(leftOffset, 0), new Point(leftOffset, ActualHeight));
            leftOffset += column.ActualWidth;
        }

        base.OnRender(dc);
    }
}

Where do I wanna go with this:

  • I have a public github where all the code is on. (Currently working in the other-approach branch). GITHUB
  • When I am done I want to make an nuget package of this (there is no opensource solution for a schedular right now).
kevingoos
  • 3,785
  • 4
  • 36
  • 63

1 Answers1

1

Now the next thing that I need to do is actually make the grid cells clickable. Does anybody have an idea on doing that?

You could override the OnMouseDown method get the position of the mouse pointer relative to the Grid using the solution from here:

Get Grid Cell by mouse click

You could then insert an element in the corresponding cell. Please refer to the following sample code.

public class BorderGrid : Grid
{
    public BorderGrid()
    {
        Background = Brushes.Transparent;
    }

    protected override void OnRender(DrawingContext dc)
    {
        double leftOffset = 0;
        double topOffset = 0;
        Pen pen = new Pen(Brushes.Gray, 0.5);
        pen.Freeze();

        foreach (RowDefinition row in RowDefinitions)
        {
            dc.DrawLine(pen, new Point(0, topOffset), new Point(this.ActualWidth, topOffset));
            topOffset += row.ActualHeight;
        }

        foreach (ColumnDefinition column in ColumnDefinitions)
        {
            dc.DrawLine(pen, new Point(leftOffset, 0), new Point(leftOffset, ActualHeight));
            leftOffset += column.ActualWidth;
        }

        base.OnRender(dc);
    }

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        base.OnMouseDown(e);
        Point point = Mouse.GetPosition(this);

        int row = 0;
        int col = 0;
        double accumulatedHeight = 0.0;
        double accumulatedWidth = 0.0;

        foreach (var rowDefinition in RowDefinitions)
        {
            accumulatedHeight += rowDefinition.ActualHeight;
            if (accumulatedHeight >= point.Y)
                break;
            row++;
        }

        foreach (var columnDefinition in ColumnDefinitions)
        {
            accumulatedWidth += columnDefinition.ActualWidth;
            if (accumulatedWidth >= point.X)
                break;
            col++;
        }

        //color cell Red:
        Grid childGrid = new Grid();
        childGrid.Background = Brushes.Red;
        Grid.SetColumn(childGrid, col);
        Grid.SetRow(childGrid, row);
        Children.Add(childGrid);
    }

Note that you have to set the Background property of the Grid to a Brush in order for the mouse events to fire.

Community
  • 1
  • 1
mm8
  • 163,881
  • 10
  • 57
  • 88