2017-12-12 1 views
-2

in der folgenden StrukturAnruf Eltern Methode von Kind-Element

<Border ...> 
    <ItemsControl> 
     <ItemsControl.Template> 
      <DataTemplate> 
       <ACustomElement> 
        <Border MouseLeftButtonDown="method1"> 
       </ACustomElement> 
      </DataTemplate> 
     </ItemsControl.Template> 
    </ItemsControl> 
</Border> 

Ich möchte von innen method1 eine öffentliche Methode in der ACustomElement Klasse() aufzurufen.

Was ich bisher in method1 versucht():

var cr = ((Border)sender).Parent; 
cr.method2(); 

method2 ist eine öffentliche Methode in meiner ACustomElement Klasse. Aber es scheint die Methode nicht zu erkennen.

Ich erhalte die folgende Fehlermeldung:

'DependencyObject' does not contain a definition for 'method2' and no extension method 'method2' accepting a first argument of type 'DependencyObject' could be found (are you missing a using directive or an assembly reference?)

Vorschläge, wie dieses Problem zu lösen? Sicherlich fehlt mir nur eine Besetzung oder etwas anderes ...

Edit: Die folgenden Stil wird immer auf ACustomElement angewendet werden:

<Style TargetType="{x:Type c:ACustomElement}"> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type c:ACustomElement}"> 
       <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" /> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 
+1

Die "Parent" Eigenschaft gibt zurück ein DependencyObject.Wirf es in deinen "ACustomElement" -Typ – nkoniishvt

+0

@nkoniishvt: casting cr zu ACustomElement löst das Problem nicht, wie in meinem Kommentar in Artioms Answer erwähnt. – tg24

+0

Was genau ist ACustomElement? Ist es eine Kontrolle? – mm8

Antwort

2

Sie werfen müssen cr zu ACustomElement Typ

var cr = (ACustomElement)((Border)sender).Parent; 
cr.method2(); 

Andernfalls verweist Ihre cr Variable auf DependencyObject-Typ, wie Sie in der Ausnahme sehen.

Wenn Sie sich über die Hierarchie nicht sicher sind, verwenden Sie diese Methode, um einen übergeordneten Typ zu finden.

private T FindParent<T>(DependencyObject child) where T : DependencyObject { 
    var parent = VisualTreeHelper.GetParent(child) as T; 
    if (parent != null) 
     return parent; 
    return FindParent<T>(parent); 
} 

// usage 
private void method1(object sender, MouseButtonEventArgs e) 
{ 
    var cr = FindParent<ACustomElement>((Border)sender); 
} 

Auch DateTemplate Kind ItemsControl.ItemTemplate sein kann, aber nicht von ItemsControl.Template

<ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <local:ACustomElement> 
       <Border MouseLeftButtonDown="method1" /> 
      </local:ACustomElement> 
     </DataTemplate> 
</ItemsControl.ItemTemplate> 

aktualisieren

Und wie ich in den Kommentar hingewiesen (die Control erwartet) Fügen Sie zu der Frage einen Event-Handler direkt zu Ihrem Typ hinzu oder binden Sie einen Befehl. Warum machst du es so kompliziert?

+0

Ich habe versucht, cr in den ACustomElement-Typ zu konvertieren, aber es wird der folgende Fehler ausgegeben: Der Typ 'System.Windows.DependencyObject' kann nicht in 'ACustomElement' konvertiert werden. – tg24

+1

@ tg24 das scheint nicht richtig. Der Cast-Ansatz sollte funktionieren –

+0

@ tg24 bist du sicher, dass mein Code nicht funktioniert? Ich habe überprüft und es funktioniert gut. Außer dir scheint Xaml einen Fehler zu haben – Artiom

-1
if (sender is Border b && b.Parent is ACustomElement c) 
{ 
    c.method2(); 
} 

ist sicher und korrekt.

Da Sie vermutet haben, dass Sie eine Besetzung vermisst haben, ist die Mustererkennung besser lesbar und widerstandsfähiger als das direkte Hinzufügen dieser Besetzung.

Der Grund für den Kompilierungsfehler ist, dass Parent einfach als allgemeiner Typ eingegeben wird, der übergeordnete Elemente darstellt, nicht eine Instanz der benutzerdefinierten Elementklasse, die Sie erstellt haben.

0

Versuchen Sie, die Tag Eigenschaft des Border auf das benutzerdefinierte Steuerelement zu binden:

<ACustomElement> 
    <Border MouseLeftButtonDown="method1" Tag="{Binding RelativeSource={RelativeSource AncestorType=ACustomElement}}"> 
</ACustomElement> 

... und werfen die Tag Eigenschaft im Ereignishandler:

var cr = sender as Border; 
var ctrl = cr.Tag as ACustomElement; 
ctrl.method2(); 
+0

Dies funktioniert auch nicht. – tg24

+0

Es tut, wenn die "Struktur", die Sie gepostet haben, tatsächlich gültig ist ... was "funktioniert nicht" bedeutet? – mm8

+0

Das Xaml ist korrekt. Beachten Sie, dass ich weitere Informationen zum Stil hinzugefügt habe. "funktioniert nicht" bedeutet, dass ctrl auch nicht in der Lage ist, method2() aufzurufen, obwohl sein Typ "ACustomElement" – tg24