在WPF中处理一个附加事件的附加行为。

问题描述 投票:0回答:2

我在网上搜索了一下这个问题,但是没有收集到任何信息,我想知道是否可以让一个附加的行为来处理一个附加的事件?

我在一个类和一个行为中声明了一个事件,我将其附加到一个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);
    }
}

这是我的事件类,我在行为中是这样处理的

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);
}
wpf xaml events attachedbehaviors
2个回答
3
投票

当然可以。给我看看你的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";
    }

因为你已经将Name属性设置在 TextBoxButton 你可以在你的Window.cs后面的代码中访问它们,并且你可以很容易地编写你的处理程序。

下面是你如何使用附加属性来做所有事情。

这是新的XAML解决方案,带有附加属性。我必须创建我的自定义Interaction,因为你使用的是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>

我不得不将Behavior设置为 True 因为默认值是 false 当值不等于旧值时,适当的改变事件将被调用,我的自定义逻辑是这样的。

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

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

在属性改变事件中,当我改变时,就会像我之前提到的那样调用 falsetrue. 我告诉调度员在应用程序处于后台时执行我的代码,等到一切都初始化了。然后我发现 TextBox 并注入处理程序,当您触发 ResetInput 事件。

这是非常复杂的解决方案,但它将与附加事件和附加属性一起工作。

我强烈建议你使用后面的代码来解决这个方案。

另外,你在你的 ResetInputEventClass 类。Add和Remove方法的拼写不正确。

你应该这样写。

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


4
投票

你的问题很简单。文本框是为事件注册的,但文本框的父体却在引发事件。因此处理程序从未被调用。你可以改变事件,使其成为一个隧道事件,而不是气泡事件,或者你可以对你的文本框进行处理(给它一个名字和引用)。或者你可以得到一个文本框的句柄(给它一个名字,并在后面的代码中引用)。然后让它引发事件。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.