简体   繁体   English

如何以编程方式引发文本框TextChangedEvent

[英]How to raise a textbox TextChangedEvent programmatically

I'm using .net 4.5, in a WPF project. 我在WPF项目中使用.net 4.5。 I would like to raise a TextBox TextChangedEvent. 我想提出一个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? 我之前在Button.ClickEvent上做过同样的RaiseEvent,如何做到这一点?

this produces an error as follows: 这将产生如下错误:

Exception:Thrown: "Object of type 'System.Windows.RoutedEventArgs' cannot be converted to type 'System.Windows.Controls.TextChangedEventArgs'." 异常:抛出:“类型'System.Windows.RoutedEventArgs'的对象不能转换为类型'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'." (System.ArgumentException)引发了System.ArgumentException:“类型'System.Windows.RoutedEventArgs'的对象不能转换为类型'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. 在以后的行为中,我确实有textbox对象。

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] [EDIT2]

The textbox resides in a popup upon this popup closing an ObservableCollection is cleared, the textbox text remains, although hidden. 在关闭ObservableCollection的弹出窗口关闭后,文本框位于一个弹出窗口中,尽管隐藏了,文本框文本仍然保留。 If the popup is reopened and the textbox has text it needs to repopulate the ObservableCollection. 如果重新打开弹出窗口,并且文本框包含文本,则需要重新填充ObservableCollection。 It does this population in the textchanged behavior. 它会在文本已更改的行为中进行填充。 This is why I was thinking to fake an event. 这就是为什么我想假冒一个事件。

Manually raising .NET events is unadvisable, even if for no other reason than it is unrequired. 手动引发.NET事件是不可取的,即使出于不需要它的其他原因也是如此。 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. 如果您特别需要访问TextBox ,请进一步描述您的情况…… 有一种方法。


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. 从逻辑上考虑一下……您想要调用此方法,并且需要访问Popup TextBox中的TextBox ,并且每次打开Popup都需要执行此操作。 So why not just handle the Popup.Opened Event ?: 那么,为什么不只处理Popup.Opened事件呢?:

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

You can raise event manully like 您可以像

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

一种方法是您可以这样做。

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

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. 在文本框上是一个OnTextChanged事件,我希望在单击按钮时执行该文本框事件。

First, your WPF application, that in my case, contains just a grid with in it a textbox and a button. 首先,在我的情况下,您的WPF应用程序仅包含一个网格,其中包含一个文本框和一个按钮。

<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: 这是您的TxtTextBoxOnTextChanged事件的代码:

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. 希望对您有所帮助。

this could end in an stackoverflow because if recall the Event for your object it will again be catched by your textboxTextChangedBehavior 这可能会导致stackoverflow结束,因为如果调用对象的事件,它将再次被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? 但是,如果我正确地理解了您的弹出式窗口“ Opened并且您尝试引发TextChanged ,对吗?

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 因此您可以在_OpenFindPopup设置文本(添加#或其他内容),这将引发TextChanged ,现在您可以删除#并填充ObservableCollection

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM