Me gustaría vincular una lista de fechas a la propiedad BlackoutDates, pero realmente no parece posible. Especialmente en un escenario MVVM. ¿Alguien ha logrado algo como esto? ¿Hay algún buen control de calendario que funcione bien con MVVM?Cómo enlazar BlackoutDates en WPF Toolkit ¿Control de calendario?
Respuesta
Por su dilema DatePicker, me encontré con un corte claro utilizando las propiedades asociadas (modificado de mi uso de 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
}
Estoy seguro de que soy demasiado tarde para ayudarle a salir, pero es de esperar que alguien más lo encontrará útil.
No ese proyecto se suspendió por el momento. Todavía no estoy seguro de entender las Propiedades adjuntas, pero pensé que era una forma de hacerlo, simplemente no sabía cómo hacerlo en ese momento. Es hora de volver al carro de WPF. – nportelli
Sí, aún no estoy 100% seguro de que 'obtendré' Propiedades adjuntas, pero parece tener dos usos: 1. Una alternativa a un diccionario con clave de objeto dinámico para datos adicionales (como el objeto Canvas) o 2 .un uso similar al método de extensión de XAML. Mmm, una wiki comunitaria sobre el tema podría ser realmente interesante. –
Implementé el ejemplo anterior (la clase AttachedProperties). He creado una propiedad en mi modelo de vista así:
public CalendarBlackoutDatesCollection BlackoutDates
{
get
{
return _blackoutDates;
}
set
{
_blackoutDates = value;
this.RaisePropertyChanged(p => p.BlackoutDates);
}
}
Este inerits ViewModel de ObservableBase:
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));
}
}
}
}
Este es el XAML en la ventana que utiliza esta propiedad:
<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>
Ahora cuando quiero agregar BlackoutDates al calendario, llamo UpdateCalendarBlackoutDates en mi ViewModel:
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);
}
Esto funciona perfectamente para mí. Podría ser perfeccionado aún más cambiando el método OnRegisterCommandBindingChanged para aceptar una lista de DateRanges en lugar de un CalendarBlackoutDatesCollection, y el cambio de la propiedad a una lista como esta:
public List<CalendarDateRange> BlackoutDates
{
etc.
pero por ahora esto funciona para mí ..
Esto funcionó para mí, gracias. – dev1998
Aquí hay una versión mejorada de la respuesta de Matt que nos permite trabajar con BlackoutDates como con cualquier colección normal de Observable (no es necesario crear nuevas colecciones cada vez que desee cambiar las BlackoutDates). Almacenamos una lista de todos los calendarios y fechadores vinculados y dentro de su etiqueta almacenamos la colección utilizada en MVVM. Una modificación sencilla de la clase va a permitir trabajar con ObservableCollection <DateTime> si es necesario:
// 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
}
Aquí es ObservableCollection < DateTime versión >:
// 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
}
- 1. Wpf Toolkit. Enlazar encabezado de columna de DataGrid a DynamicResource
- 2. Cómo enlazar la propiedad local en el control de WPF
- 3. Crear un control de calendario personalizado de tamaño completo
- 4. DateTimePicker wpf toolkit binding
- 5. WPF Toolkit Calendar lleva dos clics para obtener el foco
- 6. WPF ToolKit DataGrid Performance
- 7. WPF - Cómo enlazar un DataGridTemplateColumn
- 8. WPF Toolkit Datagrid: ¿cómo desactivas la selección?
- 9. Cómo enlazar propiedades booleanas inversas en WPF?
- 10. WPF Enlazar a sí
- 11. WPF Toolkit Datagrid - Custom Tabbing
- 12. WPF toolkit datagrid texto de celda envoltura
- 13. Implementación de MVVM Light toolkit WPF Unity
- 14. WPF Calendario: Boldface especificó las fechas?
- 15. WPF Toolkit DataGrid tamaño de columna evento
- 16. WPF Toolkit - Desactivar animación de gráfico
- 17. WPF: ¿Cómo enlazar a una propiedad anidada?
- 18. ¿Cómo puedo ordenar un DataGridTemplateColumn en un WPF Toolkit DataGrid?
- 19. WPF DataGrid de WPF toolkit vs ListView - ¿algún beneficio?
- 20. Microsoft Ajax Control Toolkit contra jQuery
- 21. Enlazar un panel de pila de control de usuario a una colección observable en WPF
- 22. wpf ancho de control vinculante
- 23. Mejor control de calendario de JavaScript
- 24. Diferencia entre el calendario y el control del selector de fecha en WPF?
- 25. WPF Toolkit DatePicker Month/Year Only
- 26. WPF Toolkit Charting y IndependentValueBinding, IndependentValuePath
- 27. Control de calendario para Windows Phone 7?
- 28. XamlParseException utilizando el control de Silverlight Toolkit en Expression Blend
- 29. WPF Toolkit DataGrid Multi-Select: ¿Cómo obtener Selected Items out?
- 30. WPF toolkit DatePicker cambiar el valor predeterminado 'show calendar'
¿Qué ocurre cuando intenta unirse a BlackoutDates? ¿Estás obteniendo un error? – user200783
No Blackoutdates ni siquiera es una opción ... Supongo que estoy usando el Datepicker, pero pensé que solo usaba el calendario y un cuadro de texto. – nportelli