【问题标题】:Attached Behavior handling an Attached Event in WPF在 WPF 中处理附加事件的附加行为
【发布时间】:2013-02-28 11:35:07
【问题描述】:

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

我有一个在类中声明的事件和一个附加到 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


    【解决方案1】:

    你的问题很简单。文本框已为该事件注册,但文本框的父级正在引发它。因此,处理程序永远不会被调用。您可以更改事件以使其成为隧道事件而不是冒泡事件。或者您可以处理您的文本框(在后面的代码中给它一个名称和引用)。并让它引发事件。

    <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'd 以反击一些只字未提 -1'd 的巨魔。
    【解决方案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>
    

    我必须在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);
        }
    }
    

    当我将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 实现这一目标

    【讨论】:

    • 您的完整 xaml 丢失,我没有看到按钮,它在哪里?
    • 那个 void OnAttached() 是从哪里来的?请来一篇正确的代码。
    • OnAttached 属于 MyBehavior 类,在其中,我添加了处理程序(并在 OnDetaching 函数中删除了处理程序),我更新了 XAML 代码。
    • 让我把它放在我的视觉工作室
    • 嗯,只是想知道谁是这个答案的 -1 巨魔。 +1 反对它。
    猜你喜欢
    • 2012-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多