2011-04-26 70 views
0

我不知道如何問這個問題,但是在這裏。我有一個WPF窗口,它有一個響應TextBox的TextChanged事件的委託。當我將數據加載到窗口中,然後訂閱我的控制器類到該事件時,委託處理程序方法被調用。爲什麼委託訂閱者在事件通過後被調用?

順序是這樣的。 1.創建窗口 2.加載該窗口的數據。 3.使用TextDidChange方法訂閱窗口的TextChanged事件。

在這種情況下,即使在步驟2中發生「事件」,我的TextDidChange方法也會被調用。是否會出現這種預期行爲?如果不是,會發生什麼?編號: 下面是相關的代碼。我沒有發佈UserControl的事件處理,因爲它是樣板(如果委託!= null,則調用委託)。

從控制器構造:

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

這是一個奇怪的行爲。你能提供你的代碼嗎? – IVerzin 2011-04-27 07:36:39

回答

0

我不能告訴你肯定什麼WPF是幹什麼的,但在Windows引擎蓋下,控件的文字通常通過向窗口發送消息來更新。這放在應用程序的消息隊列中,並且只在UI線程處理消息時才處理 - 因此,如果控件正在由UI線程處理,那麼您必須完成初始化並將控制返回到主消息處理循環(或調用DoEvents()),然後控件將接收並處理消息。即它以異步方式發生。 (您也可以將消息「發佈」給控件,該控件在返回到您的代碼之前等待控件處理該消息,但可能/有可能​​WPF不以這種方式調用它)

最簡單解決方法是把「保護」變到類,以避免反應「內部」電話,並讓您的事件處理程序忽略的事件時,它被設置:

bool suppressTextChanged; 

void Initialize() 
{ 
    suppressTextChanged = true; 
    control.SetText("abcd"); 
    suppressTextChanged = false; 
    ... 
} 

void Control_TextChanged(object sender, EventArgs e) 
{ 
    if (suppressTextChanged) return; 
    ... 
} 

這是一個醜陋,但有效的解決方案。令人遺憾的是,Windows從未提供區分用戶驅動事件的方式(例如,用戶在控件中編輯它的文本已更改)和內部事件(由程序在內部更新控件驅動) - 儘管對於某些事件,您可以使用「發件人」來確定事件的來源,以確定它是如何觸發的。

+0

謝謝。這就是我所害怕的。我得出了關於後衛變量的相同結論,但那很糟糕,我想我不得不錯過一些東西。多麼痛苦。再次感謝。 – Shawn 2011-04-28 17:18:08