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