如何绑定WPF Toolkit日历控件中的BlackoutDates?

问题描述:

我想将日期列表绑定到BlackoutDates属性,但它似乎并不可行。特别是在MVVM场景中。有没有人做过这样的事情?有什么好的日历控件可以和MVVM一起玩吗?如何绑定WPF Toolkit日历控件中的BlackoutDates?

+0

当您尝试绑定到BlackoutDates会发生什么?你有错误吗? – user200783 2009-10-28 15:58:48

+0

没有Blackoutdates甚至没有选择...我想我使用Datepicker,但我认为只是使用日历和文本框。 – nportelli 2009-10-28 17:48:42

为了您的DatePicker的困境,我发现使用附加属性整洁的黑客(从我的使用化CommandBindings的修改):

class AttachedProperties : DependencyObject 
{ 

    #region RegisterBlackoutDates 

    // Adds a collection of command bindings to a date picker's existing BlackoutDates collection, since the collections are immutable and can't be bound to otherwise. 
    // 
    // Usage: <DatePicker hacks:AttachedProperties.RegisterBlackoutDates="{Binding BlackoutDates}" > 

    public static DependencyProperty RegisterBlackoutDatesProperty = DependencyProperty.RegisterAttached("RegisterBlackoutDates", typeof(System.Windows.Controls.CalendarBlackoutDatesCollection), typeof(AttachedProperties), new PropertyMetadata(null, OnRegisterCommandBindingChanged)); 

    public static void SetRegisterBlackoutDates(UIElement element, System.Windows.Controls.CalendarBlackoutDatesCollection value) 
    { 
     if (element != null) 
      element.SetValue(RegisterBlackoutDatesProperty, value); 
    } 
    public static System.Windows.Controls.CalendarBlackoutDatesCollection GetRegisterBlackoutDates(UIElement element) 
    { 
     return (element != null ? (System.Windows.Controls.CalendarBlackoutDatesCollection)element.GetValue(RegisterBlackoutDatesProperty) : null); 
    } 
    private static void OnRegisterCommandBindingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     System.Windows.Controls.DatePicker element = sender as System.Windows.Controls.DatePicker; 
     if (element != null) 
     { 
      System.Windows.Controls.CalendarBlackoutDatesCollection bindings = e.NewValue as System.Windows.Controls.CalendarBlackoutDatesCollection; 
      if (bindings != null) 
      { 
       element.BlackoutDates.Clear(); 
       foreach (var dateRange in bindings) 
       { 
        element.BlackoutDates.Add(dateRange); 
       } 
      } 
     } 
    } 

    #endregion 
} 

我敢肯定,我来不及帮你,但希望有人否则会发现它有用。

+0

暂时没有这个项目被搁置。我不确定我是否了解附加属性,但我认为这是一种方法,我当时不知道如何。现在是时候回到WPF的潮流了。 – nportelli 2010-07-07 14:05:51

+0

是的,我不是100%确定我'附加属性 - 但它似乎有两个用途:1.替代动态对象键控字典的其他数据(如画布对象),或2 。从XAML使用扩展方法。嗯,关于这个主题的社区维基可能真的很有趣。 – 2010-07-07 14:14:16

我实现了上面的例子(AttachedProperties类)。我创建像这样在我的ViewModel属性:从ObservableBase

public CalendarBlackoutDatesCollection BlackoutDates 
    { 
     get 
     { 
      return _blackoutDates; 
     } 
     set 
     { 
      _blackoutDates = value; 
      this.RaisePropertyChanged(p => p.BlackoutDates); 
     } 
    } 

此视图模型inerits:

using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.ComponentModel; 
    using System.Windows.Data; 
    using System.Collections; 

    namespace MySolution 
    { 
     public abstract class ObservableBase : INotifyPropertyChanged 
     { 
      public event PropertyChangedEventHandler PropertyChanged; 

      public void RaisePropertyChanged(string propertyName) 
      { 
       if (this.PropertyChanged != null) 
       { 
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
       } 
      } 
     } 
    } 

这是一个使用这个属性的XAML中的窗口:

<Window x:Class="MySolution.MainWindow" 

    xmlns:local="clr-namespace:MySolution"> 
    <Grid> 
        <DatePicker x:Name="datePicker" Grid.Row="0" Height="30" 
           local:AttachedProperties.RegisterBlackoutDates="{Binding BlackoutDates}"> 
        </DatePicker> 
    </Grid> 

现在当我想将BlackoutDates添加到日历中时,我在我的ViewModel中调用UpdateCalendarBlackoutDates:

private void UpdateCalendarBlackoutDates() 
    { 
     CalendarDateRange r = new CalendarDateRange(new DateTime(2010, 12, 9), new DateTime(2010, 12, 9)); 
     CalendarDateRange r2 = new CalendarDateRange(new DateTime(2010, 12, 10), new DateTime(2010, 12, 10)); 
     // Because we can't reach the real calendar from the viewmodel, and we can't create a 
     // new CalendarBlackoutDatesCollection without specifying a Calendar to 
     // the constructor, we provide a "Dummy calendar", only to satisfy 
     // the CalendarBlackoutDatesCollection... 
     // because you can't do: BlackoutDates = new CalendarBlackoutDatesCollection(). 
     Calendar dummyCal = new Calendar(); 
     BlackoutDates = new CalendarBlackoutDatesCollection(dummyCal); 
     // Add the dateranges to the BlackOutDates property 
     BlackoutDates.Add(r); 
     BlackoutDates.Add(r2); 
    } 

这对我来说非常合适。它可以通过改变OnRegisterCommandBindingChanged方法接受DateRanges而不是CalendarBlackoutDatesCollection的名单,并改变属性来像这样的列表将进一步完善:

public List<CalendarDateRange> BlackoutDates 
{ 
    etc. 

但现在这个工作对我来说..

+0

这对我有用,谢谢。 – dev1998 2016-08-15 20:21:48

这是Matt答案的改进版本,它允许我们像任何正常的Observable集合一样使用BlackoutDates(每次你想改变BlackoutDates时都不需要创建新的集合)。我们存储绑定的所有日历和日期选择器的列表,并在其标签内存储MVVM中使用的集合。类的一个简单的修改将允许在需要时使用的ObservableCollection <日期时间>工作:

// Adds a collection of command bindings to a date picker's existing BlackoutDates collection, since the collections are immutable and can't be bound to otherwise. 
// Usage: <DatePicker CalendarAttachedProperties.RegisterBlackoutDates="{Binding BlackoutDates}" > 
public class CalendarAttachedProperties : DependencyObject 
{ 
    #region Attributes 

    private static readonly List<Calendar> _calendars = new List<Calendar>(); 
    private static readonly List<DatePicker> _datePickers = new List<DatePicker>(); 

    #endregion 

    #region Dependency Properties 

    public static DependencyProperty RegisterBlackoutDatesProperty = DependencyProperty.RegisterAttached("RegisterBlackoutDates", typeof(CalendarBlackoutDatesCollection), typeof(CalendarAttachedProperties), new PropertyMetadata(null, OnRegisterCommandBindingChanged)); 

    public static void SetRegisterBlackoutDates(DependencyObject d, CalendarBlackoutDatesCollection value) 
    { 
     d.SetValue(RegisterBlackoutDatesProperty, value); 
    } 

    public static CalendarBlackoutDatesCollection GetRegisterBlackoutDates(DependencyObject d) 
    { 
     return (CalendarBlackoutDatesCollection)d.GetValue(RegisterBlackoutDatesProperty); 
    } 

    #endregion 

    #region Event Handlers 

    private static void CalendarBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     CalendarBlackoutDatesCollection blackoutDates = sender as CalendarBlackoutDatesCollection; 

     Calendar calendar = _calendars.First(c => c.Tag == blackoutDates); 

     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      foreach (CalendarDateRange dateRange in e.NewItems) 
      { 
       calendar.BlackoutDates.Add(dateRange); 
      } 
     } 
    } 

    private static void DatePickerBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     CalendarBlackoutDatesCollection blackoutDates = sender as CalendarBlackoutDatesCollection; 

     DatePicker datePicker = _datePickers.First(c => c.Tag == blackoutDates); 

     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      foreach (CalendarDateRange dateRange in e.NewItems) 
      { 
       datePicker.BlackoutDates.Add(dateRange); 
      } 
     } 
    } 

    #endregion 

    #region Private Methods 

    private static void OnRegisterCommandBindingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     Calendar calendar = sender as Calendar; 
     if (calendar != null) 
     { 
      CalendarBlackoutDatesCollection bindings = e.NewValue as CalendarBlackoutDatesCollection; 
      if (bindings != null) 
      { 
       if (!_calendars.Contains(calendar)) 
       { 
        calendar.Tag = bindings; 
        _calendars.Add(calendar); 
       } 

       calendar.BlackoutDates.Clear(); 
       foreach (var dateRange in bindings) 
       { 
        calendar.BlackoutDates.Add(dateRange); 
       } 
       bindings.CollectionChanged += CalendarBindings_CollectionChanged; 
      } 
     } 
     else 
     { 
      DatePicker datePicker = sender as DatePicker; 
      if (datePicker != null) 
      { 
       CalendarBlackoutDatesCollection bindings = e.NewValue as CalendarBlackoutDatesCollection; 
       if (bindings != null) 
       { 
        if (!_datePickers.Contains(datePicker)) 
        { 
         datePicker.Tag = bindings; 
         _datePickers.Add(datePicker); 
        } 

        datePicker.BlackoutDates.Clear(); 
        foreach (var dateRange in bindings) 
        { 
         datePicker.BlackoutDates.Add(dateRange); 
        } 
        bindings.CollectionChanged += DatePickerBindings_CollectionChanged; 
       } 
      } 
     } 
    } 

    #endregion 
} 

这里是的ObservableCollection <日期时间>版本:

// Adds a collection of command bindings to a date picker's existing BlackoutDates collection, since the collections are immutable and can't be bound to otherwise. 
// Usage: <DatePicker hacks:AttachedProperties.RegisterBlackoutDates="{Binding BlackoutDates}" > 
public class CalendarAttachedProperties : DependencyObject 
{ 
    #region Attributes 

    private static readonly List<Calendar> _calendars = new List<Calendar>(); 
    private static readonly List<DatePicker> _datePickers = new List<DatePicker>(); 

    #endregion 

    #region Dependency Properties 

    public static DependencyProperty RegisterBlackoutDatesProperty = DependencyProperty.RegisterAttached("RegisterBlackoutDates", typeof(ObservableCollection<DateTime>), typeof(CalendarAttachedProperties), new PropertyMetadata(null, OnRegisterCommandBindingChanged)); 

    public static void SetRegisterBlackoutDates(DependencyObject d, ObservableCollection<DateTime> value) 
    { 
     d.SetValue(RegisterBlackoutDatesProperty, value); 
    } 

    public static ObservableCollection<DateTime> GetRegisterBlackoutDates(DependencyObject d) 
    { 
     return (ObservableCollection<DateTime>)d.GetValue(RegisterBlackoutDatesProperty); 
    } 

    #endregion 

    #region Event Handlers 

    private static void CalendarBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     ObservableCollection<DateTime> blackoutDates = sender as ObservableCollection<DateTime>; 

     Calendar calendar = _calendars.First(c => c.Tag == blackoutDates); 

     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      foreach (DateTime date in e.NewItems) 
      { 
       calendar.BlackoutDates.Add(new CalendarDateRange(date)); 
      } 
     } 
    } 

    private static void DatePickerBindings_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) 
    { 
     ObservableCollection<DateTime> blackoutDates = sender as ObservableCollection<DateTime>; 

     DatePicker datePicker = _datePickers.First(c => c.Tag == blackoutDates); 

     if (e.Action == NotifyCollectionChangedAction.Add) 
     { 
      foreach (DateTime date in e.NewItems) 
      { 
       datePicker.BlackoutDates.Add(new CalendarDateRange(date)); 
      } 
     } 
    } 

    #endregion 

    #region Private Methods 

    private static void OnRegisterCommandBindingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) 
    { 
     Calendar calendar = sender as Calendar; 
     if (calendar != null) 
     { 
      ObservableCollection<DateTime> bindings = e.NewValue as ObservableCollection<DateTime>; 
      if (bindings != null) 
      { 
       if (!_calendars.Contains(calendar)) 
       { 
        calendar.Tag = bindings; 
        _calendars.Add(calendar); 
       } 

       calendar.BlackoutDates.Clear(); 
       foreach (DateTime date in bindings) 
       { 
        calendar.BlackoutDates.Add(new CalendarDateRange(date)); 
       } 
       bindings.CollectionChanged += CalendarBindings_CollectionChanged; 
      } 
     } 
     else 
     { 
      DatePicker datePicker = sender as DatePicker; 
      if (datePicker != null) 
      { 
       ObservableCollection<DateTime> bindings = e.NewValue as ObservableCollection<DateTime>; 
       if (bindings != null) 
       { 
        if (!_datePickers.Contains(datePicker)) 
        { 
         datePicker.Tag = bindings; 
         _datePickers.Add(datePicker); 
        } 

        datePicker.BlackoutDates.Clear(); 
        foreach (DateTime date in bindings) 
        { 
         datePicker.BlackoutDates.Add(new CalendarDateRange(date)); 
        } 
        bindings.CollectionChanged += DatePickerBindings_CollectionChanged; 
       } 
      } 
     } 
    } 

    #endregion 
}