WPF:处理大量路由事件

WPF:处理大量路由事件,wpf,Wpf,我需要您对以下问题的建议: 假设您有一个MyView类型(UserControl),它定义了一个路由事件IsSelectedChanged。每次更改myView.IsSelected属性值时,都会引发该值 此外,还有一个MyContainer(Canvas),其中包含大量MyView类型的子元素。MyContainer已路由事件MyViewsSelectChanged,该事件在MyViewsSelection更改时引发。MyViewsSelection是一组MyView对象,其IsSelecte

我需要您对以下问题的建议: 假设您有一个MyView类型(UserControl),它定义了一个路由事件IsSelectedChanged。每次更改myView.IsSelected属性值时,都会引发该值

此外,还有一个MyContainer(Canvas),其中包含大量MyView类型的子元素。MyContainer已路由事件MyViewsSelectChanged,该事件在MyViewsSelection更改时引发。MyViewsSelection是一组MyView对象,其IsSelected属性设置为true。MyContainer将为每个子级处理MyView.IsSelectedChanged,并将其MyViewSelection状态提供给MyContainerParent(面板)

MyContainerParent将处理myContainer.MyViewsSelectChanged事件

我担心的问题是,我的应用程序将在很大一部分MyView对象上执行不足,从而导致一种“野火”事件

我们将非常感谢您对防止此问题的任何建议

谢谢

一些代码:

BatchView.IsSelectedChanged(MyView):

公共静态只读路由事件IsSelectedChangedEvent=EventManager.RegisterRoutedEvent(
“IsSelectedChanged”,
路线策略。直接,
类型(RoutedEventHandler),
类型(批处理视图)
);
/// 
///在更改IsSelected属性值时发生。
/// 
公共活动路线已选定,但未更改{
添加{AddHandler(IsSelectedChangedEvent,value);}
remove{RemoveHandler(IsSelectedChangedEvent,value);}
}
void raiseSelectionChangedEvent(){
RoutedEventArgs e=新的RoutedEventArgs(IsSelectedChangedEvent,this.BatchViewModel);
提出事件(e);
Debug(“IsSelectionChanged:{0};IsSelected={1}”、this.BatchViewModel.Description、this.IsSelected);
}
公共静态只读DependencyProperty IsSelectedProperty=DependencyProperty.RegisterAttached(
“当选”,
类型(bool),
类型(批处理视图),
新建FrameworkPropertyMetadata(false,FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.Bindstwoway默认情况下,新建属性ChangedCallback(委托(DependencyObject发送者,DependencyPropertyChangedEventArgs){
BatchView视图=发送方作为BatchView;
bool isSelected=Convert.ToBoolean(args.NewValue);
如果(视图!=null){
视图。_border.BorderBrush=isSelected?画笔。洋红色:画笔。黑色;
view.IsPrimarySelected=view.IsFocused&&isSelected;
}
})));
/// 
///获取/设置是否选择此批处理视图
/// 
公选学校{
get{return(bool)GetValue(IsSelectedProperty);}
设置{
如果(IsSelected!=值){
SetValue(IsSelectedProperty,value);
RaiseSelectionChangedEvent();
}
}
}
甘特视图(MyContainer):

静态甘特视图(){
EventManager.RegisterClassHandler(typeof(BatchView)、BatchView.IsSelectedChangedEvent、new RoutedEventHandler(委托(对象发送方、RoutedEventTargets参数){
var batchView=发送方作为batchView;
var ganttView=batchView.FindVisualParent();
如果(甘特视图!=null){
GantView.RaiseBatchViewSelectionChangedEvent();
}
args.Handled=true;
}));
}
公共静态只读路由事件批处理视图SelectionChangedEvent=EventManager.RegisterRoutedEvent(
“BatchViewsSelectionChanged”,
路线策略。直接,
类型(RoutedEventHandler),
类型(甘特视图)
);
公共事件路由EventHandler批次视图选择已更改{
添加{AddHandler(BatchViewsSelectChangedEvent,value);}
移除{RemoveHandler(BatchViewsSelectionChangedEvent,值);}
}
void raiseBatchViewSelectionChangedEvent(){
RoutedEventArgs e=新的RoutedEventArgs(批处理视图选择更改,此项);
提出事件(e);
Debug(“BatchViewsSelectChanged:{0};”,this.SelectedBatchViews.Count());
}
SchedulerView(MyContainerParent):

静态SchedulerView(){
EventManager.RegisterClassHandler(typeof(GantView),GantView.BatchViewsSelectionChangedEvent,new RoutedEventHandler(委托(对象发送方,RoutedEventTargets参数){
var schedulerView=((GanttView)sender.FindVisualParent();
如果(schedulerView!=null){
如果(schedulerView.BatchesSelectionChanged!=null){
BatchessSelectionChangeDeventargs e=新的BatchessSelectionChangeDeventargs();
e、 SelectedBatchesCount=schedulerView.GantView.SelectedBatchViews.Count();
e、 TotalBatchesDuration=schedulerView.GantView.SelectedBatchViews.Sum(bv=>bv.BatchViewModel.Model.Duration);
e、 TotalBatchesQuantity=schedulerView.GantView.SelectedBatchViews.Sum(bv=>bv.BatchViewModel.Model.Quantity);
schedulerView.BatcheSelectionChanged(schedulerView,e);
}
}
}));
}

如果您担心必须处理的事件数量。你应该重新评估你的方法。是否有方法确定用户何时完成项目选择

如果无法减少事件数量,则您可能希望实施节流,即,只有在一定时间内未收到事件时,您才处理事件

您可以自己实现这一点-例如,通过使用定时器-或者您可以使用反应式扩展(RX)油门功能

“节流”忽略可观察序列中的值 后跟指定源的到期时间之前的另一个值 和“决斗时间”

您可以在找到RX at和Trottle at的文档。显然你可以
public static readonly RoutedEvent IsSelectedChangedEvent = EventManager.RegisterRoutedEvent(
        "IsSelectedChanged", 
        RoutingStrategy.Direct, 
        typeof(RoutedEventHandler), 
        typeof(BatchView)
    );
/// <summary>
/// Occurs when IsSelected property value is changed.
/// </summary>
public event RoutedEventHandler IsSelectedChanged {
        add { AddHandler(IsSelectedChangedEvent, value); }
        remove { RemoveHandler(IsSelectedChangedEvent, value); }
    }
void RaiseIsSelectionChangedEvent() {
        RoutedEventArgs e = new RoutedEventArgs(IsSelectedChangedEvent, this.BatchViewModel);
        RaiseEvent(e);
        Logger.Debug("IsSelectionChanged: {0}; IsSelected = {1}", this.BatchViewModel.Description, this.IsSelected);
    }
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.RegisterAttached(
        "IsSelected",
        typeof(bool),
        typeof(BatchView),
        new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(delegate(DependencyObject sender, DependencyPropertyChangedEventArgs args) {
        BatchView view = sender as BatchView;
        bool isSelected = Convert.ToBoolean(args.NewValue);
        if ( view != null ) {
            view._border.BorderBrush = isSelected ? Brushes.Magenta : Brushes.Black;
            view.IsPrimarySelected = view.IsFocused && isSelected;
        }
    })));
/// <summary>
/// Get/set whether this batch view is selected
/// </summary>
public bool IsSelected {
        get { return (bool)GetValue(IsSelectedProperty); }
        set {
            if ( IsSelected != value ) {
                SetValue(IsSelectedProperty, value);
                RaiseIsSelectionChangedEvent();
            }
        }
    }
static GanttView() {
        EventManager.RegisterClassHandler(typeof(BatchView), BatchView.IsSelectedChangedEvent, new RoutedEventHandler(delegate(object sender, RoutedEventArgs args) {
            var batchView = sender as BatchView;
            var ganttView = batchView.FindVisualParent<GanttView>();
            if ( ganttView != null ) {
                ganttView.RaiseBatchViewsSelectionChangedEvent();
            }
            args.Handled = true;
        }));
    }

public static readonly RoutedEvent BatchViewsSelectionChangedEvent = EventManager.RegisterRoutedEvent(
        "BatchViewsSelectionChanged",
        RoutingStrategy.Direct,
        typeof(RoutedEventHandler),
        typeof(GanttView)
    );
public event RoutedEventHandler BatchViewsSelectionChanged {
        add { AddHandler(BatchViewsSelectionChangedEvent, value); }
        remove { RemoveHandler(BatchViewsSelectionChangedEvent, value); }
    }
void RaiseBatchViewsSelectionChangedEvent() {
        RoutedEventArgs e = new RoutedEventArgs(BatchViewsSelectionChangedEvent, this);         
        RaiseEvent(e);
        Logger.Debug("BatchViewsSelectionChanged: {0};", this.SelectedBatchViews.Count());
    }
static SchedulerView() {
        EventManager.RegisterClassHandler(typeof(GanttView), GanttView.BatchViewsSelectionChangedEvent, new RoutedEventHandler(delegate(object sender, RoutedEventArgs args) {              
            var schedulerView = ((GanttView)sender).FindVisualParent<SchedulerView>();
            if ( schedulerView != null ) {
                if ( schedulerView.BatchesSelectionChanged != null ) {
                    BatchesSelectionChangedEventArgs e = new BatchesSelectionChangedEventArgs();
                    e.SelectedBatchesCount = schedulerView.GanttView.SelectedBatchViews.Count();
                    e.TotalBatchesDuration = schedulerView.GanttView.SelectedBatchViews.Sum<BatchView>(bv => bv.BatchViewModel.Model.Duration);
                    e.TotalBatchesQuantity = schedulerView.GanttView.SelectedBatchViews.Sum<BatchView>(bv => bv.BatchViewModel.Model.Quantity);
                    schedulerView.BatchesSelectionChanged(schedulerView, e);
                }
            }
        }));
    }
static GanttView() {            
    EventManager.RegisterClassHandler(typeof(BatchView),   BatchView.IsSelectedChangedEvent, new RoutedEventHandler(delegate(object sender, RoutedEventArgs args) {
            var batchView = sender as BatchView;
            var ganttView = batchView.FindVisualParent<GanttView>();
            if ( ganttView != null && !ganttView._batchViewIsSelectedChangedEventQueued ) {
                ganttView._batchViewIsSelectedChangedEventQueued = true;
                System.Timers.Timer eventTrigger = new System.Timers.Timer(100) { AutoReset = false };
                eventTrigger.Start();
                eventTrigger.Elapsed += new System.Timers.ElapsedEventHandler(delegate(object timer, System.Timers.ElapsedEventArgs e) {
                    ganttView._batchViewIsSelectedChangedEventQueued = false;
                    ganttView.Dispatcher.Invoke(new Action(delegate() { ganttView.RaiseBatchViewsSelectionChangedEvent(); }), DispatcherPriority.Normal, null);
                });             
            }
            args.Handled = true;
        }));
}