2017-05-09 1 views
0

Also habe ich die folgende Klasse ...Spiel Art der Steuerung mit der Basisklasse

public partial class CommandBar : UserControl { .. } 

..., die ich wie so in der ASCX-Datei enthalten ...

<%@ Register Src="~/.../CommandBar.ascx" TagName="CommandBar" TagPrefix="uc1" %> 

... 

<uc1:CommandBar ID="CommandBarTop" runat="server" ... /> 

Meine Ziel im Moment ist es, eine generische Methode zu erstellen, die es einem Benutzer ermöglicht, alle Steuerelemente rekursiv nur lesend zu setzen. Die Methode sollte einen optionalen Parameter bereitstellen, um eine List<Type> zu ignorierende Steuerelemente anzugeben. In dieser Liste möchte ich diese CommandBar mit typeof(CommandBar) übergeben, um diese zu ignorieren.

Alles funktioniert wie erwartet, aber ich habe ein wenig Mühe herauszufinden, die richtige Art, diese Typen zu entsprechen.

Betrachten Sie Folgendes;

Object o; // control to check, in this case the `CommandBarTop` object 
Type t; // type to ignore 

ich erwartet hatte es so so einfach zu sein:

if (o is t){ 
    // ignore 
} 

... aber ich bekomme eine Syntax Ausnahme „Ein konstanter Wert wird erwartet“. Also habe ich es mit der folgenden Einrichtung versucht:

Es kompilierte, aber nicht wie erwartet funktioniert. Das Problem scheint ein Typ-Fehltreffer zu sein. Wirft man einen Blick auf den Debugger bekomme ich folgendes:

t => {Name = "CommandBar" FullName = "My.Name.Space.Controls.CommandBar"} System.Type {System.RuntimeType} 
o => {ASP.controls_commandbar_ascx} object {ASP.controls_commandbar_ascx} 

o.base ist eigentlich vom Typ t aber vor allem ist es nicht zugänglich und zweite sollte die Methode generisch sein, einen Basistyp Überprüfung nicht immer wahrscheinlich passen Mach was ich will.

Ich nehme an, dass ASP.NET einen Steuerelementwrapper zur Laufzeit generiert, der dann an den Benutzer gesendet wird. Diese Annahme basiert auf der Assembly-Codebasis, die ich im Debugger sehe. Es sagt der folgende:

t.Assembly.CodeBase => "file:///.../bin/My.Name.Space.Project.DLL" string 
o.GetType().Assembly.CodeBase => "file:///C:/Windows/Microsoft.NET/Framework/.../Temporary ASP.NET Files/root/.../App_Web_....DLL" string 

Ich habe auch versucht, den Typ GUID passende aber da sie im Grunde nicht vom gleichen Typ sind, die entweder nicht funktioniert.


EDIT 1

Ich dachte, es könnte helfen, wenn ich Ihnen meine Methode zeigen die Kontrollen einzustellen rekursiv

public static void SetControlRecursivelyReadOnly(Object control, Boolean readOnly, IEnumerable<Type> controlTypesToIgnore = null) 
{ 
    if (null == control) 
    { 
     return; 
    } 

    new List<KeyValuePair<Type, String>> 
    { 
     // define all types which are relevant to access possible child controls 
     new KeyValuePair<Type, String>(typeof(ControlCollection), "Controls"), 
     new KeyValuePair<Type, String>(typeof(TableRow), "Rows"), 
     new KeyValuePair<Type, String>(typeof(TableCell), "Cells") 
    }.ForEach(x => 
       { 
        // get defined property 
        Object property = typeof(Reflection).GetMethod("GetProperty") 
                 .MakeGenericMethod(x.Key) 
                 .Invoke(null, 
                   new[] 
                   { 
                    control, 
                    x.Value 
                   }); 

        // check if property is found and is IENumerable 
        if (!(property is IEnumerable)) 
        { 
         return; // continues the foreach loop 
        } 

        // call recursive 
        foreach (Object o in (IEnumerable) property) 
        { 
         // <--- TODO CHECK IF CONTROL TYPE SHOULD BE IGNORED ---> 
         SetControlRecursivelyReadOnly(o, readOnly); 
        } 
       }); 

    // set relevant properties accordingly to readOnly parameter 
    new List<Tuple<PropertyInfo, Boolean>> 
      { 
       new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("ReadOnly"), readOnly), 
       new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("EnableButtons"), !readOnly), 
       new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("Enabled"), !readOnly) 
      }.Where(x => null != x.Item1) 
      .ToList() 
      .ForEach(x => x.Item1.SetValue(control, x.Item2, null)); 
} 

kommend auf meine Frage jetzt zu Nur-Lesen; Hat jemand eine Idee, wie man dieses Problem lösen kann?

Vielen Dank im Voraus!

+0

Was meinen Sie, wenn Sie über Komponenten sprechen? Vielleicht "Controls" (TextBox, Label ...)? Können Sie einige Beispiele hinzufügen? – Emanuele

+0

@Emanuele jawohl, ich meine Kontrollen. Ich habe meine Frage entsprechend aktualisiert. die Beispiele, die Sie mit TextBox, Label usw. gegeben haben. ist genau was ich meine. Ofc gibt es auch Panels, Tabellen, DropDownLists, .. welche manchmal eine Eigenschaft namens "Controls", "Rows" oder "Cells" selbst haben, deshalb implementiere ich es rekursiv, um zu allen Controls innerhalb der Seite –

Antwort

0

Sie müssen alle Steuerelemente auf Ihrer Seite rekursiv durchlaufen.

public void FindChildControlsRecursive(Control control) 
    { 
     foreach (Control childControl in control.Controls) 
     { 
      // add .BaseType in the next line if it's a UserControl 
      if (childControl.GetType() == typeof(T)) 
      { 
       _foundControls.Add((T)childControl); 
      } 
      else 
      { 
       FindChildControlsRecursive(childControl); 
      } 
     } 
    } 

    private readonly List<T> _foundControls = new List<T>(); 
    public IEnumerable<T> FoundControls 
    { 
     get { return _foundControls; } 
    } 

Auf die gleiche Weise können Sie eine Eigenschaft festlegen, die Steuerelemente zum Ausschließen enthält.

können Sie überprüfen: How to get the "typeof" of a custom user control

+0

zu gelangen, die ich bereits habe rekursive Funktion, das ist nicht das Problem. das Problem ist die Übereinstimmung des Typs. Ihr Ansatz mit 'control.GetType() == typeof (T)' funktioniert nicht. Da T bereits ein Typ ist, gibt das Aufrufen von typeof (T) einen RuntimeType zurück, was ich nicht brauche. Auch weil das Steuerelement nicht vom selben Typ ist, wird es nicht funktionieren. lese meine Frage erneut –

+0

Sorry, ich würde meinen Beitrag bearbeiten. Versuchen Sie BaseType zu verwenden. Ich würde meine Lösung auf VS überprüfen. – Emanuele

+0

Ja, BaseType bezieht sich in der Tat auf den richtigen Typ, die Übereinstimmung mit diesem sollte funktionieren. Das Problem ist, wenn ich es implementiere, um immer den BaseType zu überprüfen, bin ich mir ziemlich sicher, dass das zu der Zeit am meisten nicht funktioniert, weil der BaseType von ziemlich jedem Control 'WebControl' ist. Wenn ich der Methode sage, WebControl dann zu ignorieren Nichts wird passieren. Ich dachte schon über diesen Ansatz nach, aber es scheint, dass ich ziemlich schnell Probleme bekommen würde –

0

mit dem Namen prop Ihre Art versuchen. So etwas wie unten sollte

arbeiten

if (typeof(o).Name == t.GetType().Name) { // ignore }

+0

Aufruf '.GetType()' auf t (die bereits vom Typ 'Type') wird return a 'System.RuntimeType' .. das wird nicht funktionieren. auch der Name ist nicht derselbe –

Verwandte Themen