C# 如果您';当在WPF中的gridview上滚动时,您是否尝试取消对事件的缓冲?需要学生练习的提示吗
我需要某种去盎司事件功能,但我觉得我需要运行它遇到的第一个对象事件(在我只单击一次箭头,它就会跳下一个对象的情况下),第一个和最后一个对象之间的每个人都会被弹回,最后一个将被调用(如果我最终停止向下滚动箭头。) 你将如何解决这个问题C# 如果您';当在WPF中的gridview上滚动时,您是否尝试取消对事件的缓冲?需要学生练习的提示吗,c#,.net,wpf,gridview,C#,.net,Wpf,Gridview,我需要某种去盎司事件功能,但我觉得我需要运行它遇到的第一个对象事件(在我只单击一次箭头,它就会跳下一个对象的情况下),第一个和最后一个对象之间的每个人都会被弹回,最后一个将被调用(如果我最终停止向下滚动箭头。) 你将如何解决这个问题 private DateTime lastEvent = DateTime.Now; private readonly TimeSpan EventDelay = TimeSpan.FromMilliseconds(500); privat
private DateTime lastEvent = DateTime.Now;
private readonly TimeSpan EventDelay = TimeSpan.FromMilliseconds(500);
private async Task SelectionChanged(object sender, EventArgs e)
{
if (DateTime.Now - lastEvent > EventDelay)
{
// DO STUFF
}
lastEvent = DateTime.Now;
}
我使用来自Rx.NET的解决方案来解决此类问题。来自文档:
去盎司-仅当某个特定时间跨度已过且未发射另一项时,才从可观测项发射一项
注意:在.NET版本中,去盎司操作符被称为Throttle
。需要添加的nuget包被称为System.Reactive
您可以从ListView/GridView的SelectionChanged
事件创建一个可观察对象。下面是一个小示例:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ListView.ItemsSource = new[] { "One", "Two", "Three", "Four" };
var selectionChangedObservable = Observable.FromEventPattern
<SelectionChangedEventHandler, SelectionChangedEventArgs>(
h => ListView.SelectionChanged += h,
h => ListView.SelectionChanged -= h);
var debouncedObservable = selectionChangedObservable
.Throttle(TimeSpan.FromSeconds(1))
.ObserveOnDispatcher();
debouncedObservable.Subscribe(SelectionChangedDebounced);
}
private void SelectionChangedDebounced(EventPattern<SelectionChangedEventArgs> ep)
{
Console.WriteLine($"Item {ListView.SelectedItem} selected");
}
}
使用的简单模式是在事件中添加task.delay并忽略任何旧的任务,直到新任务用完为止 您在基本设计中已经说明了这一点,因为您没有将所选内容和要处理的内容传递到处理程序中。事件之间没有区别。它们都只是“发生了某件事”,然后是另一件“发生了某件事”
如果你考虑鼠标移动去抖动,这可能更清楚:
private Point lastPosition = new Point();
private async void ShaperCanvas_MouseMove(object sender, MouseEventArgs e)
{
await Task.Delay(200);
Point pt = e.GetPosition(ShaperCanvas);
if (lastPosition == pt)
{
在这里,我们可以看到用户是否停止移动鼠标
在您的代码中,您似乎需要一个LastSelectedItem。
因此,您的逻辑将隐藏本地选择的内容。
等等。
查看所选内容是否与开始时的内容不同。
如果是不同的,那么发生了另一个事件,所以退出
您可能还需要一个isbusy标志,以便在处理其中一个时不会发生任何事情
比如:
private async Task SelectionChanged(object sender, EventArgs e)
{
var LastSelectedItem = CurrentSelectedItem;
await Task.Delay(200);
if(CurrentSelectedItem != LastSelectedItem)
{
resume;
}
// DO STUFF
你已经尝试过什么了?堆栈溢出实际上不是一个询问和回答假设性问题的地方,而是一个寻找具体问题答案的地方。在我看来,这听起来像是一个问题。说到这里,我会使用某种倒计时。假设用户按下箭头向下,这会触发事件,但在实际执行我想要的任何操作之前t大约为500毫秒,如果用户在该时间段内再次按下向下箭头,则倒计时将重新开始。然后,您可以实现一些功能,在第一次按下时立即执行事件,因此当计时器不计时时down@MindSwipe我尝试了类似的方法,我已经更新了线程。如果您能提供代码示例?您是否在此事件中使用MVVM设计模式或代码隐藏?感谢您的回答…我正在使用MVVM方法,是否可以将其放在viewmodel中?@TobiasHoeferMy事件也是这种类型:如果我将其调整为与此一起使用,会是什么情况?公共委托任务异步处理程序(对象发送方,事件args args);公共事件AsyncHandler OnSelectionChanged;我更新了线程,无法使用ListView.SelectionChanged:/Yes您可以在viewmodel中使用代码。问题是事件的委托类型。事件委托不应具有返回类型。您需要从“任务AsyncHandler(对象,事件参数)”更新事件delagate'到'void asynchHandler(object EventArgs')。当然,这只是简单的'EventHandler'委托。我将在我的答案中添加一个ViewModel示例。我想我将改为使用EventHandler。您介意将您的版本更改为EventHandler版本吗?这样可以修复非等待的动态调用吗?
private Point lastPosition = new Point();
private async void ShaperCanvas_MouseMove(object sender, MouseEventArgs e)
{
await Task.Delay(200);
Point pt = e.GetPosition(ShaperCanvas);
if (lastPosition == pt)
{
private async Task SelectionChanged(object sender, EventArgs e)
{
var LastSelectedItem = CurrentSelectedItem;
await Task.Delay(200);
if(CurrentSelectedItem != LastSelectedItem)
{
resume;
}
// DO STUFF