Delegate zum Entfernen einen Event Handlers


HPB

Erfahrenes Mitglied
#1
Hallo,
ich würde gerne über einen delegate einen Eventhandler zu einem UIElement hinzufügen und später wieder löschen.
D.h. statt
b.TextChanged +=new TextChangedEventHandler(b_TextChanged);
verwende ich eineen Delegate:
private delegate void BTextChangedDelegate(object sender, TextChangedEventArgs e);
b.TextChanged += new TextChangedEventHandler(bTextChangedDelegate);



Das funktioniert wunderbar. Den gleichen Mechanismus möchte ich aber beim Entfernen des Events anwenden, d.h. statt
b.TextChanged -= b_TextChanged;
würde ich schreiben b.TextChanged -= bTextChangedDelegate;

Dann bekomme ich jedoch den Fehler
Cannot implicitly convert type 'BTextChangedDelegate' to 'System.Windows.Controls.TextChangedEventHandler'

Könnt ihr mir sagen, warum das nicht funktioniert?

Mein Beispiel Programm:
Code:
using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication6
{
    public partial class MainPage : UserControl
    {
        private delegate void BTextChangedDelegate(object sender, TextChangedEventArgs e);
        public MainPage()
        {
            InitializeComponent();           
        }

        void b_TextChanged(object sender, TextChangedEventArgs e)
        {
            DebugInfo.Text = "DebugInfo:\nEventFired:\t" + (sender as TextBox).Text;
        }

        void RegisterEvent(TextBox b, BTextChangedDelegate bTextChangedDelegate)
        {
            b.TextChanged += new TextChangedEventHandler(bTextChangedDelegate);
            //b.TextChanged +=new TextChangedEventHandler(b_TextChanged);
        }

        void DeregisterEvent(TextBox b, BTextChangedDelegate bTextChangedDelegate)
        {
            b.TextChanged -= bTextChangedDelegate;      //<--- COMPILE-ERROR
            //b.TextChanged -= b_TextChanged;
        }

        private void Register_Click(object sender, RoutedEventArgs e)
        {
            RegisterEvent(b, b_TextChanged);
        }
        
        private void Deregister_Click(object sender, RoutedEventArgs e)
        {
            DeregisterEvent(b, b_TextChanged);
        }
    }
}
HTML:
<UserControl x:Class="SilverlightApplication6.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:Generic="clr-namespace:System.Collections.Generic;assembly=System" mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Margin="50">
            <TextBox x:Name="b" BorderThickness="2" Text="TextToBeChanged"/>
            <Button x:Name="Register_button" Content="Reregister Event" Click="Register_Click"/>
            <Button x:Name="Deregister_button" Content="Deregister Event" Click="Deregister_Click"/>
            <TextBox x:Name="DebugInfo" Text="DebugInfo"/>
        </StackPanel>
    </Grid>
</UserControl>
(im Anhang als kleines MS Visual Studio Projekt)

Danke für eure Hilfe!
 

Anhänge

HPB

Erfahrenes Mitglied
#3
Danke für den Tipp, damit kompiliert es zumindest.

Aber wenn ich mein Beispiel starte, dann klappt das deregistrieren nicht. Nach dem Deregistrieren wird das Event immer noch gefeuert.

Es scheint aber nicht unbedingt an dem -= new TextChangedEventHandler... zu liegen.
Wenn ich direkt versuche den Handler wegzunehmen via b.TextChanged -=b_TextChanged; dann wird das Event auch weiterhin geworfen.
 

Anhänge

Zuletzt bearbeitet:

Turri

Erfahrenes Mitglied
#4
Hmm, hast du vielleicht das Event öfters Registriert als Deregistriert?
Du kannst ja beim RegisterEvent und DeregisterEvent einen Counter hoch und runter zählen lassen, und den mal ausgeben...
 

HPB

Erfahrenes Mitglied
#5
Nee, eigentlich nicht. Wenn du mein Mini-Beispiel startest, dann kannst du das registrieren und das deregistrieren manuel anstoßen über zwei Knöpfe. Auch mehrfahres deregistrieren bingt nichts.
 

Turri

Erfahrenes Mitglied
#6
Hallo,

ich hab mal bisschen rumgekniffelt.
Hier eine Lösung die funktioniert.
Anders habe ich es mit Delegat aber auch nicht hinbekommen.

Vielleicht hilft es dir ja weiter.

Hier die MainPage.xaml.cs
C#:
using System.Windows;
using System.Windows.Controls;

namespace SilverlightApplication6
{
    public partial class MainPage : UserControl
    {
        private delegate void BTextChangedDelegate(object sender, TextChangedEventArgs e);

        BTextChangedDelegate dele = null;
        public MainPage()
        {
            InitializeComponent();
            this.dele = this.b_TextChanged;         
        }

        void b_TextChanged(object sender, TextChangedEventArgs e)
        {
            DebugInfo.Text = "DebugInfo:\nEventFired:\t" + (sender as TextBox).Text;
        }

        void RegisterEvent(TextBox b, BTextChangedDelegate bTextChangedDelegate)
        {
            b.TextChanged += new TextChangedEventHandler(bTextChangedDelegate);
        }

        void DeregisterEvent(TextBox b, BTextChangedDelegate bTextChangedDelegate)
        {
            b.TextChanged -= new TextChangedEventHandler(bTextChangedDelegate);
        }

        private void Register_Click(object sender, RoutedEventArgs e)
        {            
            RegisterEvent(b, dele);
        }
        
        private void Deregister_Click(object sender, RoutedEventArgs e)
        {            
            DeregisterEvent(b, dele);
        }
    }
}
 
Gefällt mir: HPB

Neue Beiträge