附加行为处理WPF中的附加事件

时间:2013-02-28 11:35:08

标签: wpf xaml events attachedbehaviors

关于这个问题我用Google搜索但是无法收集任何信息,我想知道附加行为是否有可能处理附加事件?

我在类中声明了一个事件,并且我附加到TextBox控件的行为,单击一个按钮时将引发该事件。我在我的行为中添加了此事件的处理程序,并在事件处理程序中编写了逻辑,但它未执行。所以,我想知道附加行为是否可能处理附加事件?

class ResetInputEventClass
{
    public static readonly RoutedEvent ResetInputEvent =  EventManager.RegisterRoutedEvent("ResetInput",
      RoutingStrategy.Bubble,
      typeof(RoutedEventHandler),
      typeof(ResetInputEventClass));

    public static void AddResetInputEventHandler(DependencyObject d, RoutedEventHandler handler)
    {
        UIElement uie = d as UIElement;
        if (uie == null)
        {
            return;
        }
        uie.AddHandler(ResetInputEventClass.ResetInputEvent, handler);
    }

    public static void RemoveResetInputEventHandler(DependencyObject d, RoutedEventHandler handler)
    {
        UIElement uie = d as UIElement;
        if (uie == null)
        {
            return;
        }
        uie.RemoveHandler(ResetInputEventClass.ResetInputEvent, handler);
    }
}

这是我的Event类,这就是我在行为中处理它的方式

public class MyBehavior : Behavior<TextBoxBase>
{
    public MyBehavior()
    {
        // Insert code required on object creation below this point.

    }        

    protected override void OnAttached()
    {
        base.OnAttached();
        // Insert code that you would want run when the Behavior is attached to an object.
        ResetInputEventClass.AddResetInputEventHandler(AssociatedObject, OnResetInputEvent);
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        // Insert code that you would want run when the Behavior is removed from an object.
        ResetInputEventClass.RemoveResetInputEventHandler(AssociatedObject, OnResetInputEvent);
    }

    private void OnResetInputEvent(Object o, RoutedEventArgs e)
    {
        //Logic
    }
}

这是我的XAML代码:

<Grid x:Name="LayoutRoot">
    <StackPanel>
        <TextBox Margin="5" Text="Bye" TextWrapping="Wrap" Width="150">
            <i:Interaction.Behaviors>
                <local:MyBehavior/>
            </i:Interaction.Behaviors>
        </TextBox>
        <TextBox Margin="5" Text="Bye" TextWrapping="Wrap" Width="150">
            <i:Interaction.Behaviors>
                <local:MyBehavior/>
            </i:Interaction.Behaviors>
        </TextBox>
        <Button Name="MyButton" Content="Save" Width="50" Height="25" Click="MyButton_Click"/>
    </StackPanel>
</Grid>

我在按钮的点击事件中提升了该事件

private void MyButton_Click(object sender, RoutedEventArgs e)
{
    RoutedEventArgs eventArgs = new RoutedEventArgs(ResetInputEventClass.ResetInputEvent,e.OriginalSource);
    RaiseEvent(eventArgs);
}

2 个答案:

答案 0 :(得分:3)

你的问题很简单。文本框已为事件注册,但文本框的父级正在提升它。因此从不调用处理程序。您可以更改事件以使其成为隧道事件而不是冒泡。或者你可以获得文本框的句柄(在后面的代码中给它一个名称和引用)。并举起活动。

<Grid x:Name="LayoutRoot">
<StackPanel>
<TextBox Margin="5" x:Name="byeTextBox" Text="Bye" TextWrapping="Wrap" Width="150">
                    <i:Interaction.Behaviors>
                        <local:MyBehavior/>
                    </i:Interaction.Behaviors>
                </TextBox>
<Button Name="MyButton" Content="Save" Width="50" Height="25" Click="MyButton_Click"/>
</StackPanel>
</Grid>

您的代码隐藏应该看起来像这样

private void MyButton_Click(object sender, RoutedEventArgs e)
        {
            RoutedEventArgs eventArgs = new RoutedEventArgs(ResetInputEventClass.ResetInputEvent,e.OriginalSource);
            byeTextBox.RaiseEvent(eventArgs);
        }

这应该可以解决你的问题。

答案 1 :(得分:2)

当然有可能。告诉我你的XAML,我会告诉你附加事件如何触发附加行为。

<强>被修改

我没有看到您为什么要使用附加行为和附加事件,因为您可以在代码中执行所有操作。

以下是如何在代码中执行所有操作:

这是没有附加属性的XAML:

<Grid>
        <StackPanel>
            <TextBox x:Name="txtBox" Margin="5" Text="Bye" TextWrapping="Wrap" Width="150"/>
            <Button Name="MyButton" Content="Save" Width="50" Height="25" Click="MyButton_Click"/>
        </StackPanel>
</Grid>

这是背后的代码。

    public MainWindow()
    {
        InitializeComponent();
    }

    private void MyButton_Click(object sender, RoutedEventArgs e)
    {
        this.txtBox.Text = "hello";
    }

因为您已在TextBoxButton设置了Name属性,所以您可以从Window.cs中的代码访问它们,并且您可以轻松地编写处理程序。

以下是使用附加属性执行所有操作的方法:

这是具有附加属性的解决方案的新XAML。我必须创建自定义交互,因为您使用的是Expression Blend或silverlight而不是纯WPF。

<Grid x:Name="LayoutRoot">
        <StackPanel i:Interaction.Behaviour="True">
            <TextBox x:Name="txtBox" Margin="5" Text="Bye" TextWrapping="Wrap" Width="150"/>
            <Button Name="MyButton" Content="Save" Width="50" Height="25" Click="MyButton_Click"/>
        </StackPanel>
    </Grid>

private void MyButton_Click(object sender, RoutedEventArgs e)
    {
        RoutedEventArgs eventArgs = new RoutedEventArgs(ResetInputEventClass.ResetInputEvent,e.OriginalSource);
        RaiseEvent(eventArgs);
    }

我必须在True上设置行为,因为默认值为false,当值不等于old时,将使用我的自定义逻辑调用propery changed事件:

 public class Interaction : DependencyObject
{
    // Using a DependencyProperty as the backing store for Behaviour.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty BehaviourProperty =
        DependencyProperty.RegisterAttached("Behaviour", typeof(bool), typeof(Interaction), new PropertyMetadata(false, new PropertyChangedCallback(OnBehaviourChanged)));

    private static void OnBehaviourChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        StackPanel sp = (StackPanel)d;
        sp.Dispatcher.BeginInvoke(new Action(() =>
        {
            TextBox tb =  VisualTreeHelper.GetChild(sp, 0) as TextBox;


            ResetInputEventClass.AddResetInputHandler(sp, new RoutedEventHandler((o, a) =>
            {
                // Do here whatever you want, call your custom expressions.
                tb.Text = "hello";
            }));

        }), System.Windows.Threading.DispatcherPriority.Background);
    }
}

在我将false更改为true时已经提到的内部属性更改事件。通过告诉调度员在应用程序处于后台时执行我的代码,我等到所有内容都已初始化。然后我找到TextBox并注入将在您触发ResetInput事件时调用的处理程序。

这是一个非常复杂的解决方案,但它可以用于附加事件和附加属性。

我强烈建议您使用此方案背后的代码。

你在ResetInputEventClass课程中犯了一个错误。添加和删​​除方法拼写错误。

这就是你应该写的:

public static void AddResetInputHandler(DependencyObject d, RoutedEventHandler handler)
    {
        UIElement uie = d as UIElement;
        if (uie == null)
        {
            return;
        }
        uie.AddHandler(ResetInputEventClass.ResetInputEvent, handler);
    }

    public static void RemoveResetInputHandler(DependencyObject d, RoutedEventHandler handler)
    {
        UIElement uie = d as UIElement;
        if (uie == null)
        {
            return;
        }
        uie.RemoveHandler(ResetInputEventClass.ResetInputEvent, handler);
    }

玩得开心,我希望我能帮助你。

你也可以通过Commands

实现这一目标