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