【问题标题】:Silverlight DatePicker binding broken - what can I do to fix this?Silverlight DatePicker 绑定损坏 - 我可以做些什么来解决这个问题?
【发布时间】:2012-02-14 22:00:47
【问题描述】:

我遇到了一个非常简单的 DatePicker 绑定问题。

我有一个 ListBox 绑定到具有 DateTime 属性的对象列表。我的页面有一个编辑部分,用于更改所选项目。这很好用 - 当我在 DatePicker 中更新日期时,ListBox 会显示我更新的日期。

但是,当我随后选择另一个项目时,DatePicker 控件也会错误地更新新项目的日期。

这是我的代码:

C#:

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>

我该如何解决这个问题?

【问题讨论】:

    标签: silverlight data-binding


    【解决方案1】:

    似乎解决此问题的最简单方法是延迟选择的更改,以便 DatePicker 在更改选择之前更新正确的绑定。

    【讨论】:

    • 您能详细说明一下吗?我有一个数据网格,其中有一列包含日期选择器(通过单元格模板)。数据网格会自动按日期排序,此时其他行也会更改为新输入的值。听起来像同一个错误。我用 DispatcherTimer 延迟了排序方法,但这并没有解决问题。
    【解决方案2】:

    我在 Silverlight 3 项目中出现了一个非常相似的错误(请参阅我在 Craig 的回答中的评论)。经过大量的试验和错误,创建一个扩展的 DatePicker 为我解决了这个问题。没有赢得漂亮奖,但我猜一个烂摊子的子类可能会是烂摊子。

    xaml 中的数据绑定:

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

    日期选择器扩展:

    /// <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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 2020-09-12
      • 2019-08-02
      • 2019-10-30
      • 1970-01-01
      相关资源
      最近更新 更多