为什么我的自定义模板CalendarDayButton不听PropertyChanged?

时间:2013-05-22 12:57:20

标签: wpf xaml calendar wpf-controls

我已经创建了一个基于Calendar的自定义控件,它也实现了。它的功能是它可以根据Observable Collection中是否存在该日来对代码天进行着色。

我为日历的CalendarDayButton组件创建了一个模板(通过复制日历源代码),其中我添加了一个矩形,可用于显示背景颜色。矩形填充属性通过多重绑定和使用转换器绑定到我的DataContext和我的自定义日历。

当CalendarDayButton的DataContext发生更改时,这很有效,但它似乎完全忽略了对我的observable集合所做的所有更改。这意味着,当我添加或删除一天时,日历不会更新它的外观。我在转换器Convert函数中有一个断点。它会在日历加载时调用,但不会在我添加日期时调用。

我还在我的日历的OnPropertyChanged函数中创建了一个断点,它的PropertyChanged总是为null。我还尝试将我的ObservableCollection转换为DependencyProperty,并使用单个Bindings对象。没变。看起来像矩形的绑定事件并没有创建一个监听器。

现在我将日历的日期更改为DateTime.Min然后再返回,这会导致每个按钮的数据上下文更新为解决此问题,但这很难看。

我想更好地理解这种行为。我也对更新由集合中的更改触发的日历日按钮的颜色的正确解决方案感兴趣。

这是我的自定义日历:

namespace Lekstuga
{
    public class ColouredCalendar : Calendar, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public DependencyProperty DoneMarkedDaysProperty =
            DependencyProperty.Register("DoneMarkedDaysAttribute", typeof (ObservableCollection<DateTime>),
                                        typeof (ColouredCalendar));

        public ObservableCollection<DateTime> DoneMarkedDaysAttribute
        {
            get { return (ObservableCollection<DateTime>) GetValue(DoneMarkedDaysProperty); }
            set { SetValue(DoneMarkedDaysProperty, value); }
        }

        static ColouredCalendar()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ColouredCalendar), new FrameworkPropertyMetadata(typeof(ColouredCalendar)));
        }

        public ColouredCalendar()
            : base()
        {
            SetValue(DoneMarkedDaysProperty, new ObservableCollection<DateTime>());

            DoneMarkedDaysAttribute.Add(new DateTime(2013, 05, 01));
            DoneMarkedDaysAttribute.Add(new DateTime(2013, 05, 02));
            DoneMarkedDaysAttribute.Add(new DateTime(2013, 05, 03));
        }  

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public void AddNextDay()
        {
            var greenDays = DoneMarkedDaysAttribute;
            var nextDay = greenDays[greenDays.Count - 1].AddDays(1.0d);

            DoneMarkedDaysAttribute.Add(nextDay);

            OnPropertyChanged("DoneMarkedDaysAttribute");
        }

        public void Refresh()
        {
            var curDate = DisplayDate;
            DisplayDate = DateTime.MinValue;
            DisplayDate = curDate;
        }
    }
}

这是我的转换器:

namespace Lekstuga
{
    class DayToColorConverter : IMultiValueConverter
    {
        private SolidColorBrush myGreenBrush = new SolidColorBrush(Colors.Green);
        private SolidColorBrush myIndigoBrush = new SolidColorBrush(Colors.Indigo);

        public DayToColorConverter()
        {

        }

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            var tmp = (values[0] == null);
            if (tmp == false)
            {
                tmp = (values[1] == null);
            }
            if (tmp == true) return null;

            var day = ((DateTime) values[1]).Date;
            var markedDays = (ObservableCollection<DateTime>)values[0];

            if ( markedDays.Contains(day) )
            {
                return myGreenBrush;
            }


            return null;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

最后我的CalendarDayButton模板的相关部分:

...
                        <Rectangle x:Name="TodayBackground" RadiusX="1" RadiusY="1" Opacity="0" Fill="#89B8FF"/>
                        <Rectangle x:Name="SelectedBackground" RadiusX="1" RadiusY="1" Opacity="0" Fill="{TemplateBinding Background}"/>
                        <Rectangle x:Name="Background" RadiusX="1" RadiusY="1" Opacity="0" Fill="{TemplateBinding Background}"/>
                        <Rectangle x:Name="DoneMarkingBackground" IsHitTestVisible="False" Visibility="Visible" >
                            <Rectangle.Fill>
                                <Binding Converter="{StaticResource DayToColorConv}" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type local:ColouredCalendar}}" Mode="OneWay" />
                            </Rectangle.Fill>
                        </Rectangle>
                        <ContentPresenter
                                x:Name="NormalText"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                Margin="5,1,5,1">
                            <TextElement.Foreground>
                                <SolidColorBrush x:Name="selectedText" Color="#FF333333"/>
                            </TextElement.Foreground>
                        </ContentPresenter>
                        <Path x:Name="Blackout" Opacity="0" Margin="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" RenderTransformOrigin="0.5,0.5" Fill="#FF000000" Stretch="Fill" Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 L12.973633,11.029181 L15.191895,11.029181 L12.844727,13.999395 L15.21875,17.060919 L12.962891,17.060919 L11.673828,15.256231 L10.352539,17.060919 L8.1396484,17.060919 L10.519043,14.042364 z"/>
                        <Rectangle x:Name="DayButtonFocusVisual" Visibility="Collapsed" IsHitTestVisible="false" RadiusX="1" RadiusY="1" Stroke="#FF45D6FA"/>
...

0 个答案:

没有答案