3

我在 WPF 项目中使用 .net 4.5。我想提出一个 TextBox TextChangedEvent。这就是我所做的:

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

我之前在 Button.ClickEvent 上做过同样的 RaiseEvent,我该怎么做呢?

这会产生如下错误:

异常:抛出:“'System.Windows.RoutedEventArgs' 类型的对象无法转换为 'System.Windows.Controls.TextChangedEventArgs' 类型。” (System.ArgumentException) 引发 System.ArgumentException:“'System.Windows.RoutedEventArgs' 类型的对象无法转换为 'System.Windows.Controls.TextChangedEventArgs' 类型。”

[编辑]

实际更改的文本框文本由附加行为处理,如下所示。我想以编程方式引发事件的地方是另一个控件的附加行为。在后面的行为中,我确实有文本框对象。

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
        }
    }
}

我尝试提出事件的地方:

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); }
    }
}

[编辑2]

在此弹出窗口关闭 ObservableCollection 时,文本框驻留在弹出窗口中,但文本框文本仍然存在,尽管是隐藏的。如果重新打开弹出窗口并且文本框有文本,则需要重新填充 ObservableCollection。它在 textchanged 行为中执行此填充。这就是为什么我想伪造一个事件。

4

5 回答 5

2

手动引发 .NET 事件是不可取的,即使没有其他原因也是如此。想想看……你真的不想引发一个事件。您不是在寻求事件的功能,那么为什么要提出它呢?

如果我正确理解您的情况,那么您实际上想要做的是执行代码的特定部分。因此,您的问题是由于该部分代码当前封装在事件处理程序中而引起的。但是,这并不意味着您必须引发该事件才能执行该代码。

相反,只需将相关代码移动到一个方法中,您可以从事件处理程序以及您想要的任何其他地方调用该方法,而无需引发任何事件:

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

private void PopulateObservableCollection()
{
    // Populate ObservableCollection
}

如果您特别需要访问TextBox,请进一步描述您的情况……有办法。


更新>>>

从逻辑上考虑这个......你想调用这个方法并且你需要访问TextBoxinPopup并且你需要在每次Popup打开时都这样做。那么为什么不只处理Popup.Opened事件呢?:

private void PopupOpened(object sender, EventArgs e)
{
    // Check TextBox and Populate ObservableCollection
}
于 2014-06-24T08:40:39.080 回答
1

您可以像

    MouseButtonEventArgs args = new MouseButtonEventArgs(Mouse.PrimaryDevice,100, MouseButton.Left);
    args.RoutedEvent = UIElement.PreviewMouseLeftButtonUpEvent;
    tb.RaiseEvent(args);
于 2014-06-24T06:38:52.327 回答
0

一种方法是你可以这样做..

   EventName.Raise(this, new EventArgs());
于 2014-06-24T06:37:48.117 回答
0

为什么不直接调用事件的方法呢?我为您创建了一个小型示例应用程序:

它执行以下操作:

  • 我有一个按钮和一个文本框。文本框上有一个 OnTextChanged 事件,我希望在单击按钮时执行该文本框事件。

首先,在我的例子中,您的 WPF 应用程序只包含一个网格,其中包含一个文本框和一个按钮。

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

我知道布局明智,这是垃圾,但这只是为了演示。

在你的代码后面,你需要做一些事情:

为按钮和文本框添加事件处理程序:

public MainWindow()
{
    InitializeComponent();

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

这是您的 TxtTextBoxOnTextChanged 事件的代码:

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

如您所见,这仅显示一个消息框。

然后是您的按钮事件:

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

我希望它有所帮助。

于 2014-06-24T06:42:52.920 回答
0

这可能以堆栈溢出结束,因为如果为您的对象调用事件,它将再次被您的对象捕获textboxTextChangedBehavior

所以你可以简单地改变你的而不是创建一个循环

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

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;
    }

[编辑]

嗯,也许问题更多的是你如何努力实现你的目标。

但是,如果我正确理解您的弹出窗口Opened并且您尝试提高TextChanged,对吗?

所以你可以在你的_OpenFindPopup(添加一个#或任何东西)中设置文本,这将提高你的TextChanged,现在你可以删除#并填充你的ObservableCollection

于 2014-06-24T07:39:49.287 回答