Hank
Hank

Reputation: 2616

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.

Upvotes: 3

Views: 6764

Answers (5)

Sheridan
Sheridan

Reputation: 69959

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
}

Upvotes: 2

WiiMaxx
WiiMaxx

Reputation: 5420

this could end in an stackoverflow because if recall the Event for your object it will again be catched by your textboxTextChangedBehavior

so instead of creating a loop you can simple change your

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

to

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

        // now your textboxTextChangedBehavior does't block your event 
        args.Handled = false;
    }

[EDIT]

mhh maybe the problem is more how you try to achieve your goal.

but if i understand you correctly your popup Opened and you try to raise the TextChanged, right?

so you could set the Text in your _OpenFindPopup (add an # or what ever) which will raise your TextChanged and now you can remove the # and populate your ObservableCollection

Upvotes: 0

Complexity
Complexity

Reputation: 5820

Why don't you call the method of the event directly? I have created a small sample application for you:

It does the following:

  • I have a button and a textbox. On the textbox is a OnTextChanged event, and I want when I click on the button, to execute that textbox event.

First, your WPF application, that in my case, contains just a grid with in it a textbox and a button.

<Grid>
    <TextBox Name="txtTextBox"></TextBox>
    <Button Name="btnDemo" Content="Click me"></Button>
</Grid>

I know that layout wise, this is rubbish, but it's just for demonstrating.

In your code behind, you need to do a few things:

Add an event handler for the button and for the textbox:

public MainWindow()
{
    InitializeComponent();

    btnDemo.Click += BtnDemoOnClick;
    txtTextBox.TextChanged += TxtTextBoxOnTextChanged;
}

Here's the code for your TxtTextBoxOnTextChanged event:

private void TxtTextBoxOnTextChanged(object sender, TextChangedEventArgs textChangedEventArgs)
{
    MessageBox.Show("The textbox event has been fired.");
}

As you see, this just shows an message box.

And then the event of your button:

private void BtnDemoOnClick(object sender, RoutedEventArgs routedEventArgs)
{
    TxtTextBoxOnTextChanged(this, new TextChangedEventArgs(routedEventArgs.RoutedEvent, UndoAction.None));
}

I hope it helped.

Upvotes: 0

Dhaval Patel
Dhaval Patel

Reputation: 7601

You can raise event manully like

    MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice,100, MouseButton.Left);
    args.RoutedEvent = UIElement.PreviewMouseLeftButtonUpEvent;
    tb.RaiseEvent(args);

Upvotes: 1

Alam248
Alam248

Reputation: 1

One way is that you can do like this..

   EventName.Raise(this, new EventArgs());

Upvotes: 0

Related Questions