.net 为什么代理订户在事件通过后被调用?

.net 为什么代理订户在事件通过后被调用?,.net,wpf,events,delegates,.net,Wpf,Events,Delegates,我不知道该怎么问这个问题,但还是这样。我有一个WPF窗口,其中有一个代理,它响应TextBox的TextChanged事件。当我将数据加载到窗口中,然后将控制器类订阅到该事件时,将调用委托处理程序方法 顺序是这样的。 1.创建窗口 2.加载该窗口的数据。 3.使用TextDidChange方法订阅窗口的TextChanged事件 在这个场景中,我的textdichange方法被调用,即使“事件”发生在步骤2中。这是预期的行为吗?如果没有,会发生什么 编辑: 这是相关代码。我没有从UserCont

我不知道该怎么问这个问题,但还是这样。我有一个WPF窗口,其中有一个代理,它响应TextBox的TextChanged事件。当我将数据加载到窗口中,然后将控制器类订阅到该事件时,将调用委托处理程序方法

顺序是这样的。 1.创建窗口 2.加载该窗口的数据。 3.使用TextDidChange方法订阅窗口的TextChanged事件

在这个场景中,我的textdichange方法被调用,即使“事件”发生在步骤2中。这是预期的行为吗?如果没有,会发生什么

编辑: 这是相关代码。我没有从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);
    }

我不能确切地告诉您WPF在做什么,但是在windows的引擎盖下,通常通过向窗口发送消息来更新控件的文本。这被放置在应用程序的消息队列中,并且仅当UI线程开始处理消息时才进行处理-因此,如果控件由UI线程处理,则必须完成初始化并将控件返回到主消息处理循环(或调用DoEvents())在控件接收和处理消息之前。i、 它以异步方式发生。(您还可以向控件“发布”消息,该控件在返回到代码之前等待控件处理消息,但WPF可能没有以这种方式调用它)

最简单的修复方法是在类中放入一个“guard”变量,以避免对“internal”调用作出反应,并让事件处理程序在设置时忽略事件:

bool suppressTextChanged;

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

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

这是一个丑陋但有效的解决方案。令人遗憾的是,windows从未提供区分用户驱动事件(例如,用户在控件中编辑文本时更改的文本)和内部事件(由您的程序在内部更新控件时驱动)的方法,尽管对于某些事件,您可以使用“发送者”确定事件的来源,以确定事件是如何触发的。

这是一种奇怪的行为。你能提供你的代码吗?谢谢。这就是我害怕的。关于守卫变量,我也得出了同样的结论,但这太含糊不清了,我想我肯定遗漏了什么。多痛苦啊。再次感谢。