2012-04-03 12 views
6

Für Benutzeraktionen in meinen WPF Formen Anmeldung, ich einig globalen Event-HandlerGibt es eine eindeutige Kennung für wpf UIElement?

Ich mag hinzugefügt genau protokollieren, die das Ereignis steuern Feuer, gibt es einige eindeutige Kennung für einen wpf UIElement wie ClientId in ASP.Net?

+1

Haben Sie die Eigenschaft [FrameworkElement.Name] (http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.name.aspx) versucht? – DmitryG

+0

Ja Dmitry, aber Name kann leer sein, ich möchte nicht Name auf jeder Kontrolle ausschließlich für die Protokollierung setzen –

+0

@ArsenMkrt, die [PersistId] (http://msdn.microsoft.com/en-us/library/ system.windows.uielement.persistid.aspx) scheint genau das zu sein, wonach Sie suchen. Leider ist es jetzt veraltet und hat anscheinend keinen Ersatz. Vielleicht können Sie auf die Generierung eindeutiger Identifikatoren zurückgreifen, in diesem Fall siehe [diese Frage] (http://stackoverflow.com/q/750947/464709). –

Antwort

2

Scheint, ich fand Antwort auf meine Frage, die Antwort ist Nein, jetzt Weg, dies zu tun, wie in MSDN hier (http://msdn.microsoft.com/en-us/magazine/dd483216.aspx)

Beachten Sie, dass die Top-Level-Fenstersteuerungsdefinition kein Name-Attribut enthält. Dies ist wichtig, da, wie wir in Kürze sehen werden, , wenn Sie Testautomatisierung schreiben, eine einfache Möglichkeit, einen Verweis auf ein -Steuerelement mithilfe der MUIA-Bibliothek zu bekommen, Zugriff auf die AutomationId -Eigenschaft, , die vom Compiler aus der generiert wird Name des Steuerelements. Steuerelemente ohne XAML-Name-Attribut erhalten keine AutomationId-Eigenschaft . Diese Idee ist ein spezifisches Low-Level-Beispiel für die Bedeutung der Berücksichtigung von Anwendungsdesign-Problemen für Dinge wie Sicherheit, Erweiterbarkeit und Testautomatisierung.

0

Sie suchen nur ein Name oder x:Name, so dass die Window/UserControl/Page macht die Steuerung an den Rest der Klasse mit dem angegebenen Namen zu addieren.

<Window ...> 
    <Grid> 
     ... 

     <!-- These controls are named, so you can access them directly by name --> 
     <Button x:Name="btnMyNamedButton" ... /> 
     <Button Name="btnMyOtherNamedButton" ... /> 

     <!-- This control is not named, so you can not directly access it by name --> 
     <Button ... /> 
    <Grid> 
</Window> 

public partial class MyWindow : Window 
{ 
    public MyWindow() 
    { 
     InitializeComponent(); 

     //btnMyNamedButton can be accessed 
     //btnMyOtherNamedbutton can also be accessed 

     //The third button can be accessed, but not directly by name. 
    } 
} 

Sie können aber auch immer die FrameworkElement.Tag Objekt. Es ist beabsichtigt, um beliebige Informationen zu speichern, so dass Sie dies als eine eindeutige Kennung verwenden können, wenn Sie möchten.

+0

danke für antwort @my, aber Name ist nicht das, was ich suche, zunächst möchte ich nicht alle UI-Steuerelemente exkursiv für die Protokollierung geben, und zweitens kann es unmöglich sein, für ein Raster mit vielen Bearbeitungssteuerelemente in Zellvorlagen ... –

8

Warum verwenden Sie nicht den Hash-Code?

können Sie die Werte vergleichen, um sicherzustellen, dass sie das gleiche Objekt sind, und seine leicht, sie zu bekommen, mit .GetHashCode()


bearbeiten

Offensichtlich ist jedes Mal anders Sie das Programm ausführen, so Eigentlich ist dies eine schlechte Idee, es sei denn, Sie möchten das Protokoll jedes Mal aktualisieren, wenn der Prozess protokolliert wird. Noch möglich, obwohl

meine ich Dich könnte das Protokoll erstellt für jedes Objekt Speicher ein Hash-Wert zu der Zeit, aber ich weiß nicht, ob ich die

+0

Ich habe getestet und das Problem ist die GetHashCode() ist nur für diese Sitzung. Wenn Sie die App herunterfahren und die UI-Elemente neu starten, erhalten Sie alle neuen HashCodes. Aber immer noch +1. – Paparazzi

+0

@ExitMusic, GetHashCode wird mindestens nach dem Neustart der Anwendung geändert, wodurch das Protokoll unbrauchbar wird ... Ich möchte eine stabilere Kennung haben –

+0

Hashes sind nicht eindeutig. –

0

wie ich glaube, für Benutzeraktionen anmelden, Sie können die Eigenschaften UIAutomation tree und AutomationElement.AutomationId verwenden, da dieser Ansatz standardmäßig in allen standardmäßigen Benutzeroberflächensteuerelementen unterstützt wird. Viele Steuerelemente von Drittanbietern unterstützen auch die AutomationId für ihre Elemente (z. B. Rasterzellen). Eine AutomationId ist nützlich zum Erstellen von Testautomatisierungsskripten.

+0

Hmmmm ... scheint AutomationId sollte auch eingestellt werden, und wenn es nicht festgelegt ist, gibt es Name zurück, der in unserem Fall leer ist ... Ich denke, keine Möglichkeit zu tun, was ich suche ... –

1

Eine Möglichkeit, dies zu tun, ist mit einem benutzerdefinierten Attribut. Wie so ...

Die UIElement Sie wollen (Usercontrol zum Beispiel) protokollieren:

[UserInterfaceID(ID = "{F436E9B3-C2F6-4CF8-8C75-0A2A756F1C74}")] 
public partial class MyUserControl : UserControl 
{ 
    InitializeComponent(); 
    // or whatever... 
} 

Dann müssen Sie die benutzerdefinierte Klasse

[System.AttributeUsage(AttributeTargets.Class)] 
public class UserInterfaceIDAttribute : Attribute 
{ 
    public Guid ID { get; set; } 
} 

Jetzt in Ihrem Code-Attribut können Sie tun etwas wie das:

MyUserControl control = new MyUserControl(); 
foreach(object att in control.GetCustomAttributes(typeof(UserInterfaceAttribute),false)) 
{ 
    UserInterfaceAttribute uiAtt = (UserInterfaceAttribute)att; 
    Guid theID = uiAtt.ID; 
} 

Weil Sie das Steuerelement mit einem Attribut in der Code ändert sich der eindeutige Bezeichner nie, egal wie oft Sie die Anwendung beenden oder starten.

Natürlich ist dies ein grundlegendes Beispiel, das zeigt, wie man auf die ID zugreift, aber Sie werden wahrscheinlich irgendeine Art von aspektorientierter Programmierung verwenden wollen. Genau das mache ich mit Castle Windsor Interceptors, aber das ist außerhalb des Umfangs dieses Posts.

Idealerweise greifen Sie auf diese ID zu, wenn eine Art von Ereignis ausgelöst wird.Mit Interceptors können Sie Methodenaufrufe aufrufen, bevor sie aufgerufen werden, wobei Sie die ID wie oben gezeigt nachschlagen und die Aktion protokollieren können. Alternativ können Sie auch nur

this.GetCustomAttributes(...) 

in irgendeiner Methode verwenden, wenn ein Ereignis auf dem Steuerelement ausgelöst wird, und betten Sie Ihren dort Logging-Code. Dieses Muster ist nicht das Beste, weil Sie übergreifende Bedenken über alles streuen, was eine Art von Aspect Oriented Programming Ansatz besser macht ... aber wieder schweife ich ab und es ist außerhalb des Umfangs dieses Beitrags ... aber Sie bekommen das Idee.

Hoffe, das hilft.

+0

Warum brauche ich ein Attribut? Ich kann alle Name-Eigenschaften meiner UI-Elemente festlegen, ich möchte nur einen Weg finden, ohne etwas einzustellen, weil es in Winform möglich ist –