0

I'm using the rangepanel from this project http://www.codeproject.com/Articles/30881/Creating-an-Outlook-Calendar-Using-WPF-Part

using System;
using System.Windows;
using System.Windows.Controls;
using System.Diagnostics;

namespace Application
{
    public class RangePanel : Panel
    {
        public static DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
        public static DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(RangePanel), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));
        public static DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(RangePanel), new FrameworkPropertyMetadata(Orientation.Vertical, FrameworkPropertyMetadataOptions.AffectsArrange));
        public static DependencyProperty BeginProperty = DependencyProperty.RegisterAttached("Begin", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsArrange));
        public static DependencyProperty EndProperty = DependencyProperty.RegisterAttached("End", typeof(double), typeof(UIElement), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsArrange));

        public static void SetBegin(UIElement element, double value)
        {
            element.SetValue(BeginProperty, value);
        }

        public static double GetBegin(UIElement element)
        {
            return (double)element.GetValue(BeginProperty);
        }

        public static void SetEnd(UIElement element, double value)
        {
            element.SetValue(EndProperty, value);
        }

        public static double GetEnd(UIElement element)
        {
            return (double)element.GetValue(EndProperty);
        }

        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        public Orientation Orientation
        {
            get { return (Orientation)GetValue(OrientationProperty); }
            set { SetValue(OrientationProperty, value); }
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            double containerRange = (Maximum - Minimum);

            foreach (UIElement element in Children)
            {
                double begin = (double)element.GetValue(BeginProperty);
                double end = (double)element.GetValue(EndProperty);
                double elementRange = end - begin;

                Size size = new Size
                {
                    Width =
                        (Orientation == Orientation.Vertical)
                            ? finalSize.Width
                            : elementRange/containerRange*finalSize.Width,
                    Height =
                        (Orientation == Orientation.Vertical)
                            ? elementRange/containerRange*finalSize.Height
                            : finalSize.Height
                };

                Debug.Print((begin - Minimum) / containerRange * finalSize.Width + " " + (begin - Minimum) / containerRange * finalSize.Height);

                Point location = new Point
                {
                    X = (Orientation == Orientation.Vertical) ? 0 : (begin - Minimum)/containerRange*finalSize.Width,
                    Y = (Orientation == Orientation.Vertical) ? (begin - Minimum)/containerRange*finalSize.Height : 0
                };

                element.Arrange(new Rect(location, size));
            }

            return finalSize;
        }

        protected override Size MeasureOverride(Size availableSize)
        {
            foreach (UIElement element in Children)
            {
                element.Measure(availableSize);
            }

            double maxX = 0, maxY = 0;
            foreach (UIElement element in Children)
            {
                if (element.DesiredSize.Width > maxX)
                    maxX = element.DesiredSize.Width;
                if (element.DesiredSize.Height > maxY)
                    maxY = element.DesiredSize.Height;
            }
            availableSize.Width = maxX;
            availableSize.Height = maxY;

            return availableSize;
        }
    }
}

When I run it I get the error

'Begin' property was already registered by 'UIElement'

which refers to the begin/end properties but I don't know why.

The min and max are being set to a static value 0/1440 and the begin and end are being set through a binding (starttime/endtime are datetimes which are converted to the number of minutes since midnight, I've also verified the converter works property) as follows

<Border BorderBrush="DarkSlateGray"
    RangePanel.Begin="{Binding StartTime, Converter={StaticResource TimeToMinutes}}"
    RangePanel.End="{Binding EndTime, Converter={StaticResource TimeToMinutes}}">

    <TextBlock Text="{Binding AppointmentDescription}" Background="Red" />
</Border>

The binding however is not working which means the layout fails and all the elements are stacked on top of each other as begin is always 0 so the location becomes (0,0). I've narrowed it down to the begin and end properties not getting set/having values but I can't figure out why.

sonnyJim
  • 105
  • 1
  • 7

1 Answers1

0

I found the answer to my own question, it's in this answer.

Basically the itemscontrol needed to set the begin/end properties through the ItemsControl.ItemContainerStyle.

Here's a snippet of the modified code

<ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="calendarControls:RangePanel.Begin" Value="{Binding StartTime, Converter={StaticResource TimeToMinutes}}" />
        <Setter Property="calendarControls:RangePanel.End" Value="{Binding EndTime, Converter={StaticResource TimeToMinutes}}" />
    </Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Border BorderBrush="DarkSlateGray">
            <TextBlock Text="{Binding AppointmentDescription}" />
        </Border>
    </DataTemplate>
</ItemsControl.ItemTemplate>

It now works as expected.

sonnyJim
  • 105
  • 1
  • 7