包裹我的头周围的定制事件

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
嗨,这里是情况,form1有一个文本框,form2有一个listbox,textbox会在更新时发送它的文本字符串(在第二次不活动之后),列表框将用文本更新为新项目,a简单(HAH!)文本框之前的内容的历史记录。
还有另一个事件我需要(倒反来,当列表框项是双击时,字符串将转到文本框)但我不会问那个,我会保持简单,我想一次知道如何做一个,我可以做另一个。

这是我到目前为止所理解的(或者认为我至少要做),请纠正我,如果下面的任何东西是错的。

因此,在读取我的其他线程中提供的链接后,我知道这有四个步骤:

1)创建事件参数
2)创建使用参数的事件
3)制作一种提出事件的方法
4)制作一种方法来处理凸起的活动

因此,我现在将坚持步骤1,暂时澄清一下,并使用链接中提供的示例基于我自己的名称和粘贴如下所示:

C#:
public class TextUpdatedEventArgs : EventArgs
{
    public string NewText { get; set; }
}

因此,EverArgs将只是一个字符串(文本框中的新文本)。

我想知道的是我需要两个设置吗?我觉得这么吧?一旦引发了事件,它将将文本框中的新文本设置为事件参数,并且列表框将获取文本。我在理解这一点吗?

此外,链接没有告诉我在哪里拨打这个代码,所以我猜它在我的主要表单cs文件的命名空间部分中?

我想补充一下,这第一部分似乎对我来说最令人困惑,超越这一重点似乎更容易理解,但我猜我们会发现这是真的吗? :)
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
我想知道的是我需要两个设置吗?我觉得这么吧?一旦引发了事件,它将将文本框中的新文本设置为事件参数,并且列表框将获取文本。我在理解这一点吗?
这取决于。如果您希望任何获得对您的事件args对象的引用来混淆值,那么是的,您将希望该集是公共的。有时,事件args旨在传达单向数据(如广播),而其他事件args是事件发件人和事件接收器之间的两种方式通信。

如果您希望它基本上是读取的,那么就会让集合私有。现代OOP开始倾向于不变的物体,而不是1990年代和2000年的数据传输对象,因为多线程和并行编程的兴起。它更容易理解,无法在您下面改变。

无论如何,如果您希望该Setter是私密的,您必须以某种方式设置值。这是当您使用构造函数以及您的活动args对象时:
C#:
public class TextUpdatedEventArgs : EventArgs
{
    public string NewText { get; private set; }

    public TextUpdatedEventArgs(string newText)
    {
        NewText = newText;
    }
}
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,720
地点
悉尼,澳大利亚
编程经验
10+
我想知道的是我需要两个设置吗?我觉得这么吧?
这是一个属性,就像任何其他一样。您通常何时才能读取属性?当您希望在属性中包含的数据来读取但未写入。您是否希望在该属性中提供的数据?如果没有,它应该是只读的。

不确定你是否见过 我的博客文章 在这个主题上,但如果你还没有,你可能想检查一下。
 

约翰

C#论坛主持人
工作人员
加入
2011年4月23日
消息
1,159
地点
挪威
编程经验
10+

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,892
地点
切萨皮克,va.
编程经验
10+
嗨,这里是情况,form1有一个文本框,form2有一个listbox,textbox会在更新时发送它的文本字符串(在第二次不活动之后),列表框将用文本更新为新项目,a简单(HAH!)文本框之前的内容的历史记录。
以下关键问题是您使用UI作为数据模型。在现代编程技术中,您可以将数据模型与您的视图分开。视图(例如,您的UI)的工作是将数据模型的当前状态反映给用户,并为用户提供与数据交互的方式。是的,回到70年代早期90年代,它通常使用UI作为数据模型以及驱动业务逻辑。 (这就是为什么所有的Whiz-Bang小部件都有一个大市场,所有这些都是所有的广告,如果你喂它的正确数据,它会为你做各种花哨的图表和分析 - 甚至可能在早上煮你的早餐。 )原因用于保持UI内的数据的常见是有限的内存量和CPU处理电源随后可用。记忆力的每个字节都很重要,所以在两个不同的地方有相同的数据并没有意义。因此,如此伟大的内存和CPU效率,实际上很难思考和有关数据的原因。

因此,您面临的正确现代方法是您的数据模型应由历史记录列表组成。显示Form1时,它将在列表中占用最后一个项目,并在TextBox中显示它。每当新文本键入TextBox时,文本将添加到列表中。显示Form2时,它会显示其列表框中列表的项目。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
这是一个属性,就像任何其他一样。您通常何时才能读取属性?当您希望在属性中包含的数据来读取但未写入。您是否希望在该属性中提供的数据?如果没有,它应该是只读的。

不确定你是否见过 我的博客文章 在这个主题上,但如果你还没有,你可能想检查一下。

我读过你的博客几次,这是一个非常好的和清晰的描述,它帮助了我一个 很多 要了解自定义事件,请谢谢您的链接。

在C#6.0中,您可以只具有Getter的ReadOnly Auto-属性,需要构造函数来设置它们: C#6 - C#指南中的新功能

事实证明,这正是我需要的。谢谢。

以下关键问题是您使用UI作为数据模型。在现代编程技术中,您可以将数据模型与您的视图分开。视图(例如,您的UI)的工作是将数据模型的当前状态反映给用户,并为用户提供与数据交互的方式。是的,回到70年代早期90年代,它通常使用UI作为数据模型以及驱动业务逻辑。 (这就是为什么所有的Whiz-Bang小部件都有一个大市场,所有这些都是所有的广告,如果你喂它的正确数据,它会为你做各种花哨的图表和分析 - 甚至可能在早上煮你的早餐。 )原因用于保持UI内的数据的常见是有限的内存量和CPU处理电源随后可用。记忆力的每个字节都很重要,所以在两个不同的地方有相同的数据并没有意义。因此,如此伟大的内存和CPU效率,实际上很难思考和有关数据的原因。

因此,您面临的正确现代方法是您的数据模型应由历史记录列表组成。显示Form1时,它将在列表中占用最后一个项目,并在TextBox中显示它。每当新文本键入TextBox时,文本将添加到列表中。显示Form2时,它会显示其列表框中列表的项目。

你应该做的是添加数据 Form1 到某种排序列表,然后填充了 列表框 从那时起 Form2 创建并显示。

我从来没有在这些条款中考虑过它,这非常有趣,我要以这种方式重做,谢谢你的建议。

编辑:快速问题,避免我的克星(范围问题),在哪里可以创建这样一个列表的正确位置?
 

sh

众所周知的成员
加入
2018年9月5日
消息
1,982
编程经验
10+
如果您有两种形式,并且您想要添加列表,您将在哪里放置?

让它像这样说:
C#:
    public partial class Form1 : Form
    {
        public List<string> Lst_A = new List<string>();
        public Form1()
        {
            InitializeComponent();
        }
    }
您如何在任何相反的形式上访问这些列表中的每一个?
C#:
    public partial class Form2 : Form
    {
        public List<string> Lst_B = new List<string>();
        public Form2()
        {
            InitializeComponent();
        }
    }
或者在任何地方的课程中可以获得静态列表更好吗?

例如 :
C#:
    public static class ListBoxList
    {
        static ListBoxList()
        {

        }
        public static List<string> Form2_ListBoxItems { get; set; }
    }
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
如果您有两种形式,并且您想要添加列表,您将在哪里放置?

让它像这样说:
C#:
    public partial class Form1 : Form
    {
        public List<string> Lst_A = new List<string>();
        public Form1()
        {
            InitializeComponent();
        }
    }
您如何在任何相反的形式上访问这些列表中的每一个?
C#:
    public partial class Form2 : Form
    {
        public List<string> Lst_B = new List<string>();
        public Form2()
        {
            InitializeComponent();
        }
    }
或者在任何地方的课程中可以获得静态列表更好吗?

例如 :
C#:
    public static class ListBoxList
    {
        static ListBoxList()
        {

        }
        public static List<string> Form2_ListBoxItems { get; set; }
    }

嗯,静态清单班似乎似乎是最好的事情。我从未想过一个列表类,只有常规列表。我没有想像一个程序员:/

非常感谢您的建议,对此主题的其他问题(如果他们应该出现)我将放入一个新的线程并在此处保留我的自定义事件问题。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
所以我终于目的是我试图实际写一个事件。当有人点击列表框中的文本项时,evnt被提出,以便可以将文本复制到另一个表单文本框。

EventArgs将只是单击的文本字符串,这是我的EventArgs类:

C#:
使用 System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApp1
{
    // this event argument will contain the string clicked
    // in the history listbox
    public class ListBoxIndexChangedEventArgs : EventArgs
    {
        private readonly string _clickedText = "";

        public string ClickedText { get; }

        public ListBoxIndexChangedEventArgs(string str)
        {
            this._clickedText = str;
        }
    }
}

由于事件将在Form2上提出,因此我将事件声明放入Form2类中:

C#:
public event EventHandler<ListBoxIndexChangedEventArgs> ListBoxIndexChanged;

以下是提出了事件的方法,我在Form2类中声明了它,因为这是我将它调用的:

C#:
// method to raise the ListBoxIndexChanged event (user clicked a new item in the list
        protected virtual void OnListBoxIndexChanged(ListBoxIndexChangedEventArgs e)
        {
            if (ListBoxIndexChanged != null)
            {
                ListBoxIndexChanged(this, e);
            }
        }

假设一切都很好我的代码,有人可以帮助我下一步,处理事件的方法,我不知道它应该去哪里。我的猜测是Form1上的某个地方,因为它是目的地文本框的位置。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
我想我有它:

C#:
OnListBoxIndexChanged(new ListBoxIndexChangedEventArgs(lstbHistory.Text));

这应该进入列表框的SelectedIndexchanged事件吗?
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,720
地点
悉尼,澳大利亚
编程经验
10+
I think I have it:

C#:
OnListBoxIndexChanged(new ListBoxIndexChangedEventArgs(lstbHistory.Text));

这应该进入列表框的SelectedIndexchanged事件吗?
在里面 selectedIndexChanged. 事件处理程序。事件是提出的。处理该事件的方法是事件处理程序。这 列表框 提出了事件,您的表格处理它,然后提出自己的活动。该活动是的一部分 列表框 虽然事件处理程序是您的表格的一部分..
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
抱歉延迟,我被vb侧面跟踪。

所以,到目前为止我所做的一切都是正确的,但下一步是什么?该事件用字符串提出,所以我需要让TextBox收听事件并获取字符串?我已经读过你的Blogpost JM几次现在我发现很难"translate"如果你知道我的意思,从你的榜样到我的问题。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
我终于设法实现了我想要做的事情。自我学习与谷歌自学之学并不是一件容易的事情,所以如果有任何自我学习者在那里挣扎,我会告诉你我是如何教导的。

你应该去的第一个地方是 JM的博客文章 在这个主题上,它不会涵盖如何将事件从一种形式发送到另一个表单,而是首先阅读并了解他所显示的示例。

因此,假设我们在表单1上有一个文本框和表单2上的listbox,这是如何使用事件使您能够在列表框中单击一个项目,并将其发送到TextBox中的文本。
首先创建自定义Eventargs类,它需要一个属性来保存要发送到另一个控件的信息,在这种情况下它是一个字符串。

C#:
public class CustomEventArgs
{
    protected string _clickedText;
    public CustomEventArgs(string listBoxText) => _clickedText = listBoxText;
    public string ClickedText => _clickedText;
}

在表单2的类中,需要从中发送文本的表单,声明您的事件,并使它使用自定义Eventargs类。在这种情况下,事件称为listBoxSelectionChanged:

C#:
public partial class Form2 : Form
{
    public event EventHandler<CustomEventArgs> listboxselectionChanged.;
      
    // the rest of your code
      
}

在表单2的构造函数中,附上表格"shown"事件处理程序"shown"事件,我们这样做,因为在显示的事件处理程序中,我们将在其中将listbox的单击事件处理程序附加到列表框的单击事件(在下一步中):

C#:
public Form2()
{
    InitializeComponent();
    Shown += Form2_Shown;
}

表格2的"form shown"事件处理程序,将listbox的单击事件处理程序附加到列表框的单击事件:

C#:
private void Form2_Shown(object sender, EventArgs e)
{
    ListBox1.Click += ListBox1_Click;
}

然后,在“列表框的单击”事件处理程序中,引发事件,将您想要的数据传递给其他表单的控件:

C#:
private void ListBox1_Click(object sender, EventArgs e)
{
    listboxselectionChanged.?.Invoke(this, new CustomEventArgs(ListBox1.Text));
}

在此示例中,我使用按钮打开表单2.此代码进入任何事件处理程序打开表单(这将在表单1上)。创建了表单2的实例,下一行订阅了刚刚创建的表单的事件处理程序,onlistboxselectionChanged(在下一步中写入下一步)到事件列表汇集框,然后显示:

C#:
private void Button_Click(object sender, EventArgs e)
        {
            var form2 = new Form2();

            form2.listboxselectionChanged. += onlistboxselectionChanged.;
            form2.ShowDialog();
        }

在里面 onlistboxselectionChanged. event handler (still in form 1), the textbox's text is updated with the string data from our custom eventargs:

C#:
private void onlistboxselectionChanged.(object sender, CustomEventArgs myArgs)
{
    TextBox1.Text = myArgs.ClickedText;
}

和中提琴,它已经完成了。希望我用正确的术语,并正确解释了事情,但这作品。希望它在某个时间点帮助某人。
 
Last edited:

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,720
地点
悉尼,澳大利亚
编程经验
10+
不要忘记取消注册您的活动处理程序。对于每个'+ =',完成后应该有一个相应的' - ='。此外,这些天没有必要宣布自己的代表。只是使用通用 EventHandler.<TEventArgs> 如果要使用自定义事件args。此外,您的事件名称不应该开头"On"。可能是一个适当的事件名称 listboxclick. 然后,您将有一种提出命名的事件的方法 onlistboxclick.。方法的原因是您可以宣布它 保护 然后派生类可以覆盖它以在事件上提供自定义行为。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
哦,我明白了,这是我第一次听到未登记的活动时,我会仔细研究这一点。

我再次搞砸了命名约定,我明白了,我应该再次走过博客帖子来确保,我只是没有意识到我有错。我会尝试编辑我的帖子并重命名事件和处理程序,并根据您所描述的说明。
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,720
地点
悉尼,澳大利亚
编程经验
10+
哦,我明白了,这是我第一次听到未登记的活动时,我会仔细研究这一点。
注册事件处理程序创建两个对象之间的链接,该对象将防止垃圾收集尽快发生,因此无法注册以打破该链接。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
I've edited the post, I renamed the event to listboxselectionChanged. and the handler to onlistboxselectionChanged., this matches how you named them in your blog post I think. I also got rid of the delegate.

取消订阅此事件的时间我假设Form2右键键时是何处吗?但由于声明必须以表达1的代码进入,因此将如何形成FORM2已结束?
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,720
地点
悉尼,澳大利亚
编程经验
10+
I've edited the post, I renamed the event to listboxselectionChanged. and the handler to onlistboxselectionChanged., this matches how you named them in your blog post I think.
不。具有前缀的事件名称的方法"On"是提出事件的方法,而不是处理它的方法。这 onlistboxselectionChanged. 方法应该是与之相同的类 listboxselectionChanged. 事件。事件应该提出的唯一的地方是在该方法中,并且在您想提出活动时,您可以调用Mehod。通过这样做,任何派生的类都可以覆盖该方法并添加要在该事件上执行的自定义功能,然后从基类培养事件将执行该功能。如果包含该事件的类永远不会被继承,那么它并不重要,但我更喜欢每次都坚持“公约”。这样,我无法在我应该拥有的场合不小心不使用该公约。
取消订阅此事件的时间我假设Form2右键键时是何处吗?但由于声明必须以表达1的代码进入,因此将如何形成FORM2已结束?
你在呼唤 showdialog.。一旦该方法返回,表单已关闭。这才是重点。如果你在呼唤 表演 然后你可以简单地处理 割伤 event as well.

顺便说一下,通过呼叫显示一种形式 showdialog. 没有自动处理,所以你应该自己这样做。这样做的方式是用一个创建它 使用 声明,所以它设置在块的末尾。
 

玻璃灯

众所周知的成员
加入
2019年11月22日
消息
126
编程经验
Beginner
好的,让我确保我有这个下来,以便在我写这篇文章时获得命名约定:

C#:
form2.listboxselectionChanged. += onlistboxselectionChanged.;

private void onlistboxselectionChanged.(object sender, CustomEventArgs myArgs)
{
    TextBox1.Text = myArgs.ClickedText;
}

我正在使用"On"在错误的地方,所以我需要重命名"onlistboxselectionChanged."因为这是我处理凸起事件的方法。这个方法有一个命名约定吗?你认为什么好名字是什么?

同样在这个主题上,我使用了非常通用的名字"CustomEventArgs"就像一个自定义事件args类的清晰示例名称一样,显然这实际上是一个坏名称。我读(在你的博客上,我认为是)可以在需要使用它可以的数据时使用"carry"。所以在我的示例中(即使我现在只有一个使用)我的自定义事件args类将携带一个字符串,因此如果我只需要一个字符串,我不需要编写一个新的Eventargs类,我可以随时重用此活动。
这让我想知道命名的最佳方式。我是否根据它的数据命名它?就像是"Singlestringeventargs."由于这清楚地描述了我眼中的事件争论并根据它的功能命名它"listboxselectionEventargs."就它带来的实际数据而言,似乎有些清晰。这些名字中的任何一个都是一个不错的选择?还是别的东西会更好?
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,720
地点
悉尼,澳大利亚
编程经验
10+
对于记录,这只是一个常规,没有人需要坚持,但我建议坚持下去,因为一致性总是一个好事,你也是在框架代码中完成的方式与他们在一起的方式。我会把一个完整的例子放在一起,但它可能不是几个小时,因为它现在正在在这里接近1.00。
 
最佳 底部