Прикрепленное поведение при обработке присоединенного события в WPF

Я гуглил по этому вопросу, но не смог собрать какую-либо информацию, и мне было интересно, возможно ли для прикрепленного поведения обработать прикрепленное событие??

У меня есть событие, объявленное в классе, и поведение, которое я присоединяю к элементу управления 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 ответа

Решение

Конечно, это возможно. Покажите мне свой 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 на TextBox а также Button вы можете получить к ним доступ из кода в вашем 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 и когда значение не совпадает со старым, то событие, измененное надлежащим образом, будет вызываться с моей пользовательской логикой, например:

 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

Ваша проблема проста. Текстовое поле зарегистрировано для события, но родительское поле текстового поля вызывает его. Таким образом, обработчик никогда не вызывается. Вы можете изменить событие, чтобы сделать его туннельным событием вместо Bubbling. Или вы можете получить ручку для вашего текстового поля (дать ему имя и ссылку в коде позади). И пусть это поднимет событие.

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

и это должно решить вашу проблему.

Другие вопросы по тегам