1

我创建了一个基于日历的自定义控件,它也实现了。它的功能是它可以根据当天是否存在于 Observable Collection 中对日期进行颜色编码。

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

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

我还在日历的 OnPropertyChanged 函数中设置了一个断点,它的 PropertyChanged 始终为空。我还尝试将我的 ObservableCollection 变成一个 DependencyProperty,并对两个对象使用单个绑定。没变。似乎将事物绑定到矩形并没有创建侦听器。

现在我将日历的日期更改为 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"/>
...
4

0 回答 0