Search code examples
c#wpftextboxraiseevent

How to raise a textbox TextChangedEvent programmatically


I'm using .net 4.5, in a WPF project. I would like to raise a TextBox TextChangedEvent. This is what I have done so:

tb.RaiseEvent(new RoutedEventArgs(TextBox.TextChangedEvent));

I've done the same sort of RaiseEvent on a Button.ClickEvent before, how can I do this one?

this produces an error as follows:

Exception:Thrown: "Object of type 'System.Windows.RoutedEventArgs' cannot be converted to type 'System.Windows.Controls.TextChangedEventArgs'." (System.ArgumentException) A System.ArgumentException was thrown: "Object of type 'System.Windows.RoutedEventArgs' cannot be converted to type 'System.Windows.Controls.TextChangedEventArgs'."

[EDIT]

The actual textbox text changed is handled by an attached behavior as follows. The place where I want to programmatically raise the event is in another control's attached behavior. In the later behavior I do have the textbox object.

public class textboxTextChangedBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.TextChanged += OnTextChanged;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.TextChanged -= OnTextChanged;
        base.OnDetaching();
    }

    private void OnTextChanged(object sender, TextChangedEventArgs args)
    {
        var textBox = (sender as TextBox);
        if (textBox != null)
        {
            //Populate ObservableCollection
        }
    }
}

Place where I try to raise the event:

public class FindPopupBehavior : Behavior<Popup>
{
    protected override void OnAttached()
    {
        AssociatedObject.Opened += _OpenFindPopup;
    }

    protected override void OnDetaching()
    {
        AssociatedObject.Opened -= _OpenFindPopup;
    }

    void _OpenFindPopup(object sender, EventArgs e)
    {
        //Fake a TextBox text changed event
        if (TextBoxObject == null)
            return;

        TextBox tb = TextBoxObject as TextBox;

        if (tb.Text == "")
            return;

        tb.RaiseEvent(new RoutedEventArgs(TextBox.TextChangedEvent));
    }

    public static readonly DependencyProperty TextBoxProperty =
        DependencyProperty.Register("TextBoxObject", typeof(TextBox), typeof(FindPopupBehavior), new UIPropertyMetadata(null));

    public object TextBoxObject
    {
        get { return (object)GetValue(TextBoxProperty); }
        set { SetValue(TextBoxProperty, value); }
    }
}

[EDIT2]

The textbox resides in a popup upon this popup closing an ObservableCollection is cleared, the textbox text remains, although hidden. If the popup is reopened and the textbox has text it needs to repopulate the ObservableCollection. It does this population in the textchanged behavior. This is why I was thinking to fake an event.


Solution

  • Manually raising .NET events is unadvisable, even if for no other reason than it is unrequired. Think about it... you don't really want to raise an event. You're not seeking the functionality of the event, so why raise it?

    If I understand your situation correctly, then surely, what you actually want to do is to execute a particular section of your code. As such, your problem is caused because that section of code is currently encapsulated within an event handler. However, that doesn't mean that you have to raise that event to execute that code.

    Instead, just simply move the relevant code into a method, which you can call from the event handler and from wherever else you want and all without unnecessarily raising any events:

    private void OnTextChanged(object sender, TextChangedEventArgs args)
    {
        var textBox = (sender as TextBox);
        if (textBox != null)
        {
            PopulateObservableCollection();
        }
    }
    
    private void PopulateObservableCollection()
    {
        // Populate ObservableCollection
    }
    

    If you particularly need to access the TextBox, then please describe your situation further... there is always a way.


    UPDATE >>>

    Think about this logically... you want to call this method and you need access to the TextBox in the Popup and you need to do it each time the Popup is opened. So why not just handle the Popup.Opened Event?:

    private void PopupOpened(object sender, EventArgs e)
    {
        // Check TextBox and Populate ObservableCollection
    }