我有一个嵌入TabControl的表单(我称之为MainForm)。每次用户创建一个新选项卡时,它都会填充一个预构建面板的实例(我将调用MyPanel),其中包含许多控件。
我的MyPanel类有一个私有变量bool save_state
,每当编辑一个(可编辑的)控件时设置为false
,并在用户"时设置为true
。节省"小组的状态。
我想要一个可视标记来跟踪未保存更改的标签(例如标签" Tab1"将显示文本" Tab1 *"如果有未保存的更改) 。所以我想在我的MainForm中设置事件处理程序,它可以在MyPanel中调用一个方法来为每个控件添加处理程序。
由于并非我的所有控件都使用相同的EventHandler
类型(例如,我还需要跟踪DataGridViewRowsAddedEvent
等),我目前有几种方法将相应的处理程序添加到相应的控件(每种类型的事件处理程序一个,每个都运行相同的代码(即将save_state位设置为false并将" *"附加到选项卡文本。
例如,在MainForm.cpp
我有:
#include "MyPanel.h"
void markUnsaved(void) {
// set panel bit to false
// append " *" to tab text if we haven't already
}
void MainForm::handler1(Object ^sender, EventArgs ^e) {
markUnsaved();
}
void MainForm::handler2(Object ^sender, DataGridViewRowsAddedEventArgs ^e) {
markUnsaved();
}
void Main::FormaddNewPanelToTab(int tab_index) {
// check index is valid ...
// make the new panel
MyPanel ^new_panel = gcnew MyPanel();
new_panel->addEventHandlerToControls(gcnew EventHandler(this, &MainForm::handler1));
new_panel->addDgvEventHandlerToControls(gcnew DataGridViewRowsAddedEventHandler(this, &MainForm::handler2));
// rest of code...
}
虽然目前按预期工作,但这(以及我必须管理的其他几个事件处理程序类型)使我的代码看起来很傻。
我希望能够在MainForm
中使用单个事件处理程序,并在MyPanel
中使用单个方法对类型转换传递的事件处理程序,并将其添加到具有相应的所有控件中类型。
我尝试过简单的演员表,例如:
void MyPanel::addHandlerToControls(EventHandler ^handler) {
control_NUD->ValueChanged += handler; // this works because ValueChanged is of type EventHandler
control_DGV->RowsAdded += (DataGridViewRowsAddedEventHandler ^)handler; // this compiles but throws an exception
// rest of the code...
}
无济于事。
非常感谢任何帮助!
答案 0 :(得分:1)
我知道回答可能有点迟,但我想说明如何解决这个问题。
我建议首先摆脱构建事件处理程序的想法。这种方法可以在C#
中进行(通过一些调整)但据我所知,C++ /CLI
中无法实现。
我会去为MyPanel
类添加新事件,每次更改面板上的数据时都会调用该事件。但是为了避免向MyPanel
类中的控件事件添加许多不同的处理程序,最好创建一个通用方法来处理所有必要控件的事件并触发新事件。也许这听起来很混乱,让我展示代码:
public ref class MyPanel
{
// Add a new event
public:
event EventHandler^ DataChanged;
// Add a method that will fire new event
// this methid will be invoked on every control's event that you'll subscribe
private:
generic <typename T>
void DataChangedHandler(System::Object^ sender, T e)
{
// Fire the event
DataChanged(this, EventArgs::Empty);
}
// Once the controls are initialized you may add the event handlers
// I put it in a constructor only for example
MyPanel()
{
control_NUD->ValueChanged += gcnew EventHandler(this, &MyPanel::DataChangedHandler<EventArgs^>);
control_DGV->RowsAdded += gcnew DataGridViewRowsAddedEventHandler(this, &MyPanel::DataChangedHandler<DataGridViewRowsAddedEventArgs^>);
// and so on...
}
}
/// And now in a main form we only need to subscribe to a DataChanged event
public ref class MainForm
{
//...
// the handler
void MyHandler(Object^ sender, EventArgs^ e)
{
markUnsaved();
}
void FormaddNewPanelToTab(int tab_index)
{
// make the new panel
MyPanel ^new_panel = gcnew MyPanel();
new_panel->DataChanged += gcnew EventHandler(this, &MainForm::MyHandler);
}
//...
}
希望这有帮助。