2009-10-28 52 views
10

私はBlackoutDatesプロパティに日付のリストをバインドしたいと思いますが、実際には可能ではないようです。特にMVVMのシナリオでは。誰もこれのような何かを達成しましたか? MVVMでうまくいく優れたカレンダーコントロールはありますか?WPF ToolkitのカレンダーコントロールでBlackoutDateをバインドする方法は?

+0

あなたはBlackoutDatesにバインドしようとすると何が起こる:

// 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 <のDateTime >バージョンはありますか?エラーが発生していますか? – user200783

+0

Blackoutdatesはオプションでもありません...私はDatepickerを使用していると思いますが、カレンダーとテキストボックスを使用したと思っています。 – nportelli

答えて

16

はあなたの日付ピッカーのジレンマのために、私は(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

当分の間、そのプロジェクトは保留になっていません。私はまだAttached Propertiesを理解しているかどうかはわかりませんが、それを行う方法だと思っていました。 WPFのバンドワゴンに戻る時間。 – nportelli

+0

ええ、私は100%ではありませんが、添付プロパティはまだありますが、2つの用途があるようです:1. Canvasオブジェクトのような追加データ用のDynamic-Object-keyed辞書の代わり、または2 XAMLの拡張メソッドのような使い方。うーん、主題のコミュニティwikiは本当に興味深いかもしれません。 –

6

私は上記の例(AttachedPropertiesクラス)​​を実装しました。

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

ObservableBaseからこれのViewModel 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> 

私はこのように私のViewModelでプロパティを作成しましたBlackoutDateをカレンダーに追加する場合は、私の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); 
    } 

これは私にとって完璧に機能します。それは、さらに代わりCalendarBlackoutDatesCollectionのDateRangesの一覧を受け入れるようにOnRegisterCommandBindingChanged方法を変更し、このようなリストにプロパティを変更することで完成することができます。..

public List<CalendarDateRange> BlackoutDates 
{ 
    etc. 

が、今、これは私の作品のための

+0

これは私のために働いた、ありがとう。 – dev1998

8

ここでは、BlackoutDateを通常のObservableコレクションと同じように扱うことができる改良されたMattの答えを示します(BlackoutDateを変更するたびに新しいコレクションを作成する必要はありません)。バインドされたすべてのカレンダーと日付ピッカーのリストを格納し、タグ内にMVVMで使用されているコレクションを格納します。クラスの簡単な変更が必要な場合のObservableCollection <のDateTime >と連携できるようになります:

// 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 
} 
関連する問題