【问题标题】:Updating dependent property once instead of twice更新依赖属性一次而不是两次
【发布时间】:2013-02-09 00:02:02
【问题描述】:

在我的 ViewModel 中,我有两个属性类型的 Datetime。它们以 TwoWay 模式绑定在 XAML 中。当我更新它们中的每一个时 - OnPropertyChanged 在第三个属性的此 Datetime 属性的设置部分中引发。因此,当我同时更新两个 Datetime 属性时,我只想更新第三个属性一次,而不是更新第三个属性两次。如何归档? 应用代码:

//1
public DateTime StartDate
{
    ...
    set
    {
        this.selectedEndDate = value;
        this.OnPropertyChanged("StartDate");
        this.OnPropertyChanged("MyList");
    }
}
//2
public DateTime EndDate
{
    ...
    set
    {
        this.selectedEndDate = value;
        this.OnPropertyChanged("EndDate");
        this.OnPropertyChanged("MyList");
    }
}
//third property
public IEnumerable<MyObject> MyList
{
    get
    {
        return _data.Where(kvp=> kvp.Key.Date >= Start && kvp.Value.Date <= End).Select(kvp => kvp.Value);
    }
}

【问题讨论】:

    标签: silverlight data-binding mvvm viewmodel inotifypropertychanged


    【解决方案1】:

    您可以通过每当日期属性之一更改时启动的计时器来延迟MyList 属性更改通知。这不仅可以避免在两个属性“同时”更改时出现双重通知,而且还可以在其中一个属性更改过于频繁时防止频繁通知。

    每次属性更改都会通过停止并重新启动计时器来重置计时器,因此您可以在实际通知MyList 属性更改之前进行许多后续属性更改。

    下面的代码示例使用DispatcherTimer 来执行此任务。当然,您必须为Interval 值找到一个合理的值。

    private DispatcherTimer notifyTimer;
    
    public ViewModel()
    {
        notifyTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(200) };
        notifyTimer.Tick += OnNotifyTimerTick;
    }
    
    private void OnNotifyTimerTick(object sender, EventArgs e)
    {
        OnPropertyChanged("MyList");
        notifyTimer.Stop();
    }
    
    public DateTime StartDate
    {
        ...
        set
        {
            selectedEndDate = value;
            OnPropertyChanged("StartDate");
            notifyTimer.Stop();
            notifyTimer.Start();
        }
    }
    
    public DateTime EndDate
    {
        ...
        set
        {
            selectedEndDate = value;
            OnPropertyChanged("EndDate");
            notifyTimer.Stop();
            notifyTimer.Start();
        }
    }
    

    【讨论】:

    • @DavutGürbüz 其实这不是另一个线程,而只是 UI 线程上的一个计时器。
    • 我没有注意到“DispatcherTimer”,我以为是常规定时器,你确定你是对的。
    【解决方案2】:

    正如我所见,用户更改 startDate 第一 endDate 第二。 ?反之亦然。

    下面的代码有机会,

            bool fistChanged,endChanged;
    
             on Ctor (Constructor)
             this.PropertyChanged+=(s,p)=>
             {
                    if(p.PropertyName=="firstDate")
                    {
                     firstChanged=true;
                    }
                    if(p.PropertyName=="endDate")
                    {
                     endChanged=true;
                    }
                    if(firstChanged && endChanged)
                    {
                        this.OnPropertyChanged("MyList");
                        fistChaned=false;endChanged=false;
                    }
             }
    

    【讨论】:

    • 其实这些StartDate和EndDate是绑定到RadTimeBar telerik的控件的SelectedStartDate和SelectedEndDate的。因此可以更改这些日期之一,例如我只更改 SelectedStartDate 并且需要更改第三个属性。 BUT 当我拖动 RadTimeBar 的子控件时,我猜 SelectedStartDate 和 SelectedEndDate 都会在很短的时间内发生变化。在 BOTH 日期更改后,我想更新我的第三个属性。
    • 我也使用 RadTimeBar,RadTimeLine。我的代码应该可以帮助你。 (我只是对 Stackoverflow 的编辑器进行编码)。如果存在拖动操作,您也可以使用事件。(例如拖动完成?)
    • 我为我的 ViewModel 添加了 UpdateDates 方法,并在 RadTimeBar 的 SelectionChanged 事件处理程序中调用它。这个解决方案不太好,但谢谢你的想法。如果有人能提出更好的想法,那就太好了。
    猜你喜欢
    • 2021-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    相关资源
    最近更新 更多