【问题标题】:Method that takes a delegate as a parameter?将委托作为参数的方法?
【发布时间】:2012-12-28 04:15:53
【问题描述】:

我正在尝试创建一个将委托作为其参数之一但它不起作用的方法。我究竟做错了什么?我在windowAnimation.Completed += new EventHandler(callback) 的行上收到错误“回调是一个变量,但用作方法”。

private void animateWindowWidth(Window window, double width, double duration, Delegate callback)
{
    window.BeginInit();
    window.Dispatcher.BeginInvoke(new Action(() =>
    {
        DoubleAnimation windowAnimation = new DoubleAnimation();
        windowAnimation.Duration = new Duration(TimeSpan.FromSeconds(duration));
        windowAnimation.From = window.Width;
        windowAnimation.To = width;
        windowAnimation.FillBehavior = FillBehavior.HoldEnd;
        windowAnimation.Completed += new EventHandler(callback);
        window.BeginAnimation(Window.WidthProperty, windowAnimation);
    }), null);
    window.EndInit();
}

【问题讨论】:

  • 让我建议更优雅的 (imo) 语法:Dispatcher.BeginInvoke((Action)(() => { });
  • 谢谢。有什么不同?它只是同一件事的捷径吗?
  • 没有区别,据我所知,只是口味问题,正如我从一开始就强调的那样 :)

标签: c# .net wpf animation delegates


【解决方案1】:

我只是想解释一下为什么 Delegate 本身不起作用。

Delegate 不是真正的代表,而是一个代表。它基本上是一个包含委托的变量。这就是为什么将变量视为方法时会出错的原因。

一个简单的例子(假设你可能永远不会这样做)是如果你有两个代表来做加法。一个带有整数,另一个带有浮点数。您可以将委托存储在 Delegate 对象中,并将其传递给在一个变量上调用 DynamicInvoke() 的另一个函数:

    void MyMethod(Delegate d)
    {
        d.DynamicInvoke(leftHandSide, rightHandSide);
    }

无论两个委托中的哪一个存储在Delegate 对象中,您都可以获得相应的功能。

在您的情况下,windowAnimation.Completed 需要一个实际的委托方法,例如 EventHandler。此外,EventHandler 的构造函数需要一个委托方法。所以在这两种情况下使用Delegate 对象都行不通。

您必须将其包装在委托中或使用 lambda 函数来放置真正的方法调用

windowAnimation.Completed += (s,e) => callback.DynamicInvoke();

或将callback 更改为EventHandler,并在您要调用此方法时创建一个新的。

【讨论】:

  • 谢谢!这涵盖了我想知道的所有内容,现在我明白了我的方法不起作用的原因。
【解决方案2】:

您可以将方法签名更改为:

private void animateWindowWidth(
    Window window, 
    double width, 
    double duration, 
    EventHandler callback)

以及导致错误的那一行

windowAnimation.Completed += callback;

然后在调用该方法时创建一个新的EvenHandler。

【讨论】:

  • 谢谢,这行得通。难道就不能像以前那样做吗?
【解决方案3】:

尝试使用Action 代替Delegate 并替换此字符串:

windowAnimation.Completed += new EventHandler(callback);

用这个:

windowAnimation.Completed += (s, e) => callback();

所以,最终它应该是这样的:

private void animateWindowWidth(Window window, double width, double duration, Action callback)
{
    window.BeginInit();
    window.Dispatcher.BeginInvoke(new Action(() =>
    {
        DoubleAnimation windowAnimation = new DoubleAnimation();
        windowAnimation.Duration = new Duration(TimeSpan.FromSeconds(duration));
        windowAnimation.From = window.Width;
        windowAnimation.To = width;
        windowAnimation.FillBehavior = FillBehavior.HoldEnd;
        windowAnimation.Completed += (s, e) => callback());
        window.BeginAnimation(Window.WidthProperty, windowAnimation);
    }), null);
    window.EndInit();
}

【讨论】:

  • 谢谢,但这对我不起作用。我得到“只有赋值、调用、递增、递减、等待和新对象表达式可以用作语句”作为错误。
  • Sergey V. 你编译了吗?至少你应该写windowAnimation.Completed += (s, e) => callback.DynamicInvoke(s, e);。但是为什么要添加一个简单的事件处理程序呢?
  • 对不起,我没有编译它)。要使其正常工作,只需将 Delegate 替换为 Action。
  • 现在我把它改成了一个动作。你知道为什么我不能使用委托,需要使用你展示的动作吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 2016-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多