我不知道怎么问这个,但是这里有。我有一个WPF窗口,其中有一个委托响应TextBox的TextChanged事件。当我将数据加载到窗口中,然后将我的控制器类订阅到该事件时,将调用委托处理程序方法。
顺序就是这个。 1.创建窗口 2.加载该窗口的数据。 3.使用TextDidChange方法订阅窗口的TextChanged事件。
在这种情况下,即使在步骤2中发生“事件”,我的TextDidChange方法也会被调用。这是预期的行为吗?如果没有,可能会发生什么?
编辑: 这是相关的代码。我没有从UserControl发布事件处理,因为它是样板(如果委托!= null,则调用委托)。
来自Controller构造函数:
public ServiceRequestVM(Boolean isDataSourceProd, codExistServiceRequestSearchType requestIdOrMapNo, String aMapNumber, Decimal aRequestId) {
//create the schema and load any necessary data
_sroc = new ServiceRequestOracleController();
_sroc.IsProd = isDataSourceProd;
_isProd = isDataSourceProd;
_isNewRequest = false;
_searchType = requestIdOrMapNo;
createSchema();
if (requestIdOrMapNo == codExistServiceRequestSearchType.MapNumber) {
loadMatchingRequest(aMapNumber);
} else {
loadMatchingRequest(aRequestId);
}
Decimal _reqId = (Decimal)_serviceRequestTable.Rows[0]["REQUESTID"];
loadNotesForRequest(_reqId);
loadTagsForRequest(_reqId);
Decimal _custId = (Decimal)_serviceRequestTable.Rows[0]["CUSTOMERID"];
getNameForCustomerAndSetCustomerIdForRequest(_custId);
//configure the UI
configureUI();
customerListBoxVisibility = Visibility.Hidden;
tagListBoxVisibility = Visibility.Hidden;
//create the view (a UserControl)
_serviceRequestView = new ServiceRequestView();
_serviceRequestView.DataContext = this;
//load customers and tags
loadCustomers();
loadTags();
_shouldListBoxesBeSeen = false;
//subscribe to delegates
subscribeToRequestDelegates();
}
subscribeToRequestDelegates方法
private void subscribeToRequestDelegates() {
_serviceRequestView.addNoteButtonWasClicked += new ServiceRequestView.AddNoteButtonWasClickedHandler(addNote);
_serviceRequestView.addTagButtonWasClicked += new ServiceRequestView.AddTagButtonWasClickedHandler(addTag);
_serviceRequestView.locateButtonWasClicked += new ServiceRequestView.LocateButtonWasClickedHandler(locateMap);
_serviceRequestView.openButtonWasClicked += new ServiceRequestView.OpenButtonWasClickedHandler(openMap);
_serviceRequestView.saveButtonWasClicked += new ServiceRequestView.SaveButtonWasClickedHandler(saveRequest);
_serviceRequestView.noteWasDoubleClicked += new ServiceRequestView.NoteWasDoubleClickedHandler(openSelectedNote);
_serviceRequestView.dateCompletedLostFocus += new ServiceRequestView.DateCompletedLostFocusHandler(dateCompletedDidChange);
_serviceRequestView.titleLostFocus += new ServiceRequestView.TitleLostFocusHandler(titleDidChange);
_serviceRequestView.customerTextChanged += new ServiceRequestView.CustomerTextChangedHandler(customerTextDidChange);
_serviceRequestView.selectedCustomerChanged += new ServiceRequestView.SelectedCustomerChangedHandler(selectedCustomerDidChange);
_serviceRequestView.tagTextChanged += new ServiceRequestView.TagTextChangedHandler(tagTextDidChange);
_serviceRequestView.selectedTagChanged += new ServiceRequestView.SelectedTagChangedHandler(selectedTagDidChange);
_serviceRequestView.tagTextLostFocus += new ServiceRequestView.TagTextLostFocusHandler(tagTextLostFocus);
_serviceRequestView.customerTextLostFocus += new ServiceRequestView.CustomerTextLostFocusHandler(customerTextLostFocus);
_serviceRequestTable.ColumnChanged += new DataColumnChangeEventHandler(serviceRequestTableColumnValueDidChange);
}
答案 0 :(得分:0)
我无法确定WPF正在做什么,但在Windows的引擎盖下,控件的文本通常通过向窗口发送消息来更新。这是放在应用程序的消息队列中,只有在UI线程处理消息时才会处理 - 所以如果你的UI线程正在处理控件,那么你必须完成初始化并将控制返回到主消息处理循环(或在控件接收和处理消息之前调用DoEvents())。即它以异步方式发生。 (您也可以向控件“发布”一条消息,它等待控件在返回代码之前处理消息,但是WPF可能/可能没有以这种方式调用它)
最简单的解决方法是将“guard”变量放入您的类中以避免对“内部”调用做出反应,并让事件处理程序在设置时忽略这些事件:
bool suppressTextChanged;
void Initialize()
{
suppressTextChanged = true;
control.SetText("abcd");
suppressTextChanged = false;
...
}
void Control_TextChanged(object sender, EventArgs e)
{
if (suppressTextChanged) return;
...
}
这是一个丑陋但有效的解决方案。令人遗憾的是,Windows从未提供区分用户驱动事件的方式(例如,用户在控件中编辑它的文本更改)和内部事件(由程序在内部更新控件驱动) - 尽管对于某些事件,您可以使用“发件人”确定事件的来源,以便弄清楚它是如何被触发的。