Silverlight DatePicker Crash - What Can I Do To Fix It?

I have a very simple DatePicker binding problem that eludes me.

I have a ListBox associated with a list of objects with a DateTime property. I have part of editing my page to change the selected item. This works great - when I update the date in DatePicker, the ListBox shows my updated date.

However, when I then select another item, the DatePicker control does not update the date correctly in the new item either.

Here is my code:

FROM#:

using System; using System.Collections.ObjectModel; using System.ComponentModel; namespace BindingTest { public partial class MainPage { public MainPage() { InitializeComponent(); var vm = new ViewModel(); DataContext = vm; } } public class ViewModel : INotifyPropertyChanged { public ViewModel() { List = new ObservableCollection<Item>(); for (var n = 0; n < 10; n++) List.Add(new Item { Date = DateTime.Now.AddDays(n) }); } public ObservableCollection<Item> List { get; set; } private Item _selectedItem; public Item SelectedItem { get { return _selectedItem; } set { _selectedItem = value; OnPropertyChanged("SelectedItem"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } public class Item : INotifyPropertyChanged { private DateTime _date; public DateTime Date { get { return _date; } set { _date = value; OnPropertyChanged("Date"); } } public event PropertyChangedEventHandler PropertyChanged; private void OnPropertyChanged(string propName) { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propName)); } } } 

XAML:

 <UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="BindingTest.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <ListBox ItemsSource="{Binding List}" DisplayMemberPath="Date" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" /> <StackPanel Grid.Column="1" DataContext="{Binding SelectedItem}"> <TextBlock Text="Date:" /> <sdk:DatePicker SelectedDate="{Binding Date, Mode=TwoWay}" /> </StackPanel> </Grid> </UserControl> 

How can i fix this?

+4
source share
2 answers

It seems that the easiest way to solve this is to defer the selection change so that DatePicker updates the correct binding before changing the selection.

0
source

I had a very similar error occurring in a Silverlight 3 project (see my comment in Craig's answer). After a lot of trial and error, creating an advanced DatePicker solved the problem for me. The pretty prize doesn't win, but I think the subclass of the mess can be considered a mess.

DataBinding in xaml:

 <local:EvdDatePicker SelectedDateEx="{Binding ViewModelProperty, Mode=TwoWay}"/> 

DatePicker extension:

 /// <summary> /// Databinding on DatePicker.SelectedDate is seriously messed up (maybe because of synchronization with /// Text property?). This class extends the DatePicker and provides another property (SelectedDateEx) /// to bind to. This offers decoupling and a backup of the date value that can be reverted to. /// Additionally, selected date (of any EvdDatePicker instance) may only be changed at a defined interval. /// </summary> public class EvdDatePicker : DatePicker { // allow changes only every half second (adjust if necessary) private static TimeSpan _changeLock = TimeSpan.FromMilliseconds(500); // holds date of last user change private static DateTime _lastChange; public EvdDatePicker() { this.SelectedDateChanged += new EventHandler<SelectionChangedEventArgs>(EvdDatePicker_SelectedDateChanged); } /// <summary> /// Catch cases where SelectedDate gets changed by mistake /// </summary> void EvdDatePicker_SelectedDateChanged(object sender, SelectionChangedEventArgs e) { // measures if the change is likely caused by unwanted chain reactions if (_lastChange < DateTime.Now.Subtract(_changeLock)) { this.SelectedDateEx = e.AddedItems.Count > 0 ? (DateTime?)e.AddedItems[0] : null; _lastChange = DateTime.Now; // store last change time } // reject change (revert to old value), if the values are not synchronized by now if (this.SelectedDate != this.SelectedDateEx) this.SelectedDate = this.SelectedDateEx; } /// <summary> /// Bind to this property instead of SelectedDate /// </summary> public DateTime? SelectedDateEx { get { return (DateTime?)GetValue(SelectedDateExProperty); } set { SetValue(SelectedDateExProperty, value); } } public static readonly DependencyProperty SelectedDateExProperty = DependencyProperty.Register("SelectedDateEx", typeof(DateTime?), typeof(EvdDatePicker), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedDateExChanged))); private static void OnSelectedDateExChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { EvdDatePicker p = (EvdDatePicker)d; // initial binding, propagate to SelectedDate property DateTime? newValue = (DateTime?)e.NewValue; if (p.SelectedDate != newValue) p.SelectedDate = newValue; } } 
+1
source

Source: https://habr.com/ru/post/1392012/


All Articles