如何将EventArgs传递给函数

时间:2016-08-18 13:50:32

标签: c# winforms system.drawing

我有一个将图像绘制到表单的函数。

private void DrawImage()
{
    OpenFileDialog openfiledialog = new OpenFileDialog();
    if (openfiledialog.ShowDialog() == DialogResult.OK)
    {
        Bitmap image = (Bitmap)Image.FromFile(openfiledialog.FileName, true);
        TextureBrush texturebrush = new TextureBrush(image);
        texturebrush.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
        Graphics formGraphics = this.CreateGraphics();
        formGraphics.FillRectangle(texturebrush, new RectangleF(90.0F, 110.0F, 00, 300));
        formGraphics.Dispose();
    }
}

但如果我在按钮点击事件中写字,我将不会绘制任何图像和相同的代码。

private void button1_Click(object sender, EventArgs e)
{
    //Same code as written in DrawImage()
}

我认为问题在于它需要“EventArgs e”。我在msdn中读到了一些但不确定的地方。不知道EventArgs在表单上绘制图像的作用是什么。

有什么方法可以实现这个功能。

2 个答案:

答案 0 :(得分:1)

TL; DR

。对于你的情况,只需忽略它们。然而,它们有时可能是有用的。阅读完整的答案以了解。

完整答案

处理事件时,您会收到一个通用的EventArgs对象,如果您编写自定义事件,您可能希望收到EventArgs的自定义实现。

为简单起见,请将其视为保存与事件相关的数据的基类。

因此,例如,如果您正在实施点击事件,如图所示,您将收到两个参数:事件的来源和事件相关数据的持有者。

有时这只是无用的。就像你的样品一样。你不必接收它,也不必使用它。但是,您可以对源或事件数据执行一些检查,但这不是您的代码的目标,因此这两者都没用。

至于我,我更喜欢将我的方法与事件分开,并从事件中调用它们。我确实将每个事件绑定到"组"在课程的底部,以保持一切清洁和可读。这只是一个建议,你 找到你自己保存代码的方式。

为了这个答案,下面是两个样本:

1。无用的参数

此示例只关闭表单或窗口。

public void btn1_Click(object sender, EventArgs e) { Close(); }

2。有用的参数

考虑一个具有某种类型的数据网格的组件,该组件使用所选行的id(#)激发SelectedRowsChanged事件。

// Event declaration. You can, after that, bind it elsewhere.
public event EventHandler<SelectionEventArgs> SelectedRowsChanged;

// This is the local implementation wich will fire the event.
// Here you invoke the event with the selected rows id's.
public void OnSelectedRowsChanged() { if (SelectedRowsChanged != null) CustomSelection(this, new SelectionEventArgs(this.SelectedRows)); }

// This is the custom implementation of the EventArgs to include the
// event-related data (row id)
public class SelectionEventArgs : EventArgs
{
   public int[] SelectedRows{ get; private set; }
   public SelectionEventArgs(int[] selectedRows) { SelectedRows = selectedRows; }
}

// ... then, somewhere else on your code

this.myControl.SelectedRowsChanged += myControl_SelectedRowsChanged;

public void myControl_SelectedRowsChanged(object sender, SelectionEventArgs e)
{
   if (e.SelectedRows.Length > 0) { /* do something */ }
}

对于内心的强者,你也可以和lambda玩一点。所以,而不是:

this.button1.Click += button1_Click;
public void button1_Click(object sender, EventArgs e) { DoSomething(); }

你可能只有这个:

this.button1.Click += (s, e) => { DoSomething(); };

与第一个示例一样,事件args存在((s, e))但它们对DoSomething方法无用。

Lambda在C#5(.NET 4.5)及更高版本中可用。 有时,在表单构造函数或类似的东西中执行此操作会更容易。

答案 1 :(得分:1)

考虑以下提示来解决问题:

  • 如果您使用this.CreateGraphics在表单上绘图,那么如果表单引用,您的绘图将会消失,例如,如果您最小化并恢复它。您应该将绘图逻辑放在Paint事件中。

  • 在重构方法时,您应该将Graphics类型的参数传递给您的方法并将其用于绘图。你也不应该处理传递的参数。您应该将e.Graphics事件中的Paint传递给您的方法。

  • 在你的方法中,你应该丢弃你的画笔。将其放在using区块中。

  • 在重构方法时,应该将显示对话框的代码部分移出方法。您应该在不需要Paint事件处理程序时调用它。

  • 最好不要使用Image.FromFile来加载图像,它会锁定文件直到图像处理完毕。而是使用Image.FromStream

  • 您正在使用0Width的矩形。因此,如果您使用当前方法绘制,则由于矩形的宽度,您将看不到任何结果。

<强>代码

Bitmap image;
private void DrawImage(Bitmap image, Graphics g, Rectangle r)
{
    using (var brush = new TextureBrush(image))
    {
        brush.WrapMode = System.Drawing.Drawing2D.WrapMode.Tile;
        g.FillRectangle(brush, r);
    }
}        

private void button1_Click(object sender, EventArgs e)
{
    OpenFileDialog dialog = new OpenFileDialog();
    if (dialog.ShowDialog() == DialogResult.OK)
    {
        using (var s = new System.IO.FileStream(dialog.FileName, System.IO.FileMode.Open))
            image = new Bitmap(Image.FromStream(s));

        this.Invalidate();
    }
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
    if (image != null)
        this.DrawImage(image, e.Graphics, new RectangleF(10, 10, 200, 200));
}