Frage

Ich kämpfe mit einer Situation, die ich immer und immer wieder kommen, aber ich bin mir nicht sicher, ob die Art und Weise, dass ich Dinge tue, falsch ist oder ob ich Dinge zu tun, in einer anderen Art und Weise werden könnte.

Ein Beispiel:

Ich habe eine Windows Form, die eine Datagridview mit einigen privaten Methoden hat Validierung des Datagrid durchzuführen und die rechte Maustaste auf dem Datagridview Interpretation usw. Diese Fenster Form ist im Wesentlichen eine „abstrakt“ Klasse und wird nie direkt instanziiert.

ich dann von dieser Basisklasse erben und es auf verschiedene Weise (Schablonenmuster) anpassen z.B. definieren, die Spalten der Datagridview und insbesondere Formatierungsverfahren, die zu diesen Spalten spezifisch sind etc.

Wenn ich diese Klassen die Basisklasse verbrauchen öffentliche Methoden meine Schnittstelle bilden und ich kann die bestimmte Art von Datagridview instanziiert, die ich will und es durch die gemeinsame Schnittstelle manipulieren. Sehr schön.

Das Problem:

Das Hauptproblem ist, dass Sie eine Windows Form-Klasse als abstrakt, ohne dass die Visual Studio-Designer nicht wirklich erklären können wackelig werfen, da es nicht diese abstrakten Klassen instanziiert kann.

Einige Lösungen:

Im Moment bin ich „Umsetzung“ diese Methoden in der Basisklasse, die ich will mit außer Kraft gesetzt werden:

    throw new NotSupportedException();

so zumindest wenn ich vergesse, eine dieser Methoden außer Kraft zu setzen, die meine Schnittstelle bilden. Dies scheint eher stinkende mir obwohl ich nicht wirklich mag es.

Eine andere Lösung, die ich spielte mit war mit Vererbung zu tun, weg zusammen und definieren eine Schnittstelle (z IMyDataGrid) und implementieren, dass in jeder Klasse Datagridview (Art von Strategie-Muster). Das Problem hierbei ist aber, dass Sie die Vorteile der Wiederverwendung von Code verlieren, dass Vererbung Sinn gibt Sie, dass Sie viele verschiedene Formen zu schaffen haben, fallen eine Datagridview auf sie - effektiv kopieren und den gleichen Code in jedes einfügen. Bad.

Gibt es einen besseren Weg, dies zu erreichen versuchen?

War es hilfreich?

Lösung

Es gibt viele Möglichkeiten, um diese je nach Ihren Anforderungen zu tun.

  • Legen Sie die Form Inhalt in eine Benutzersteuerung, die eine Schnittstelle implementiert die benutzerdefinierte Logik zu tun
  • Man leite Klassen von DataGridView die eine Schnittstelle implementiert die benutzerdefinierte Logik zu tun
  • Wie bereits erwähnt, eine konkrete Klasse mit virtual Methoden verwenden stattdessen eine abstract Klasse mit
  • ...

Sie müssen, um eine Option auswählen, die Ihren Bedürfnissen am besten entspricht. Ohne zu wissen, die Domain und die Besonderheiten in dem Ihre Frage gestellt wird, ich glaube nicht, dass wir Ihnen eine 100% sichere Antwort geben können.

Andere Tipps

Schauen Sie sich dieser Methode zu wissen, wie die beiden Attribute erstellen benötigt .

Sie müssen das folgende Attribut und Typdeskriptor Klasse (Code aus UrbanPotato genommen)

// Source : taken from http://www.urbanpotato.net/default.aspx/document/2001 Seem to be down
// Allow the designer to load abstract forms
namespace YourNamespace
{

    // Place this attribute on any abstract class where you want to declare
    // a concrete version of that class at design time.
    [AttributeUsage(AttributeTargets.Class)]
    public class ConcreteClassAttribute : Attribute
    {
        Type _concreteType;
        public ConcreteClassAttribute(Type concreteType)
        {
            _concreteType = concreteType;
        }

        public Type ConcreteType { get { return _concreteType; } }
    }

    // Here is our type description provider.  This is the same provider
    // as ConcreteClassProvider except that it uses the ConcreteClassAttribute
    // to find the concrete class.
    public class GeneralConcreteClassProvider : TypeDescriptionProvider
    {
        Type _abstractType;
        Type _concreteType;

        public GeneralConcreteClassProvider() : base(TypeDescriptor.GetProvider(typeof(Form))) { }

        // This method locates the abstract and concrete
        // types we should be returning.
        private void EnsureTypes(Type objectType)
        {
            if (_abstractType == null)
            {
                Type searchType = objectType;
                while (_abstractType == null && searchType != null && searchType != typeof(Object))
                {

                    foreach (ConcreteClassAttribute cca in searchType.GetCustomAttributes(typeof(ConcreteClassAttribute), false))
                    {
                        _abstractType = searchType;
                        _concreteType = cca.ConcreteType;
                        break;
                    }
                    searchType = searchType.BaseType;
                }

                if (_abstractType == null)
                {
                    // If this happens, it means that someone added
                    // this provider to a class but did not add
                    // a ConcreteTypeAttribute
                    throw new InvalidOperationException(string.Format("No ConcreteClassAttribute was found on {0} or any of its subtypes.", objectType));
                }
            }
        }

        // Tell anyone who reflects on us that the concrete form is the
        // form to reflect against, not the abstract form. This way, the
        // designer does not see an abstract class.
        public override Type GetReflectionType(Type objectType, object instance)
        {
            EnsureTypes(objectType);
            if (objectType == _abstractType)
            {
                return _concreteType;
            }
            return base.GetReflectionType(objectType, instance);
        }


        // If the designer tries to create an instance of AbstractForm, we override 
        // it here to create a concerete form instead.
        public override object CreateInstance(IServiceProvider provider, Type objectType, Type[] argTypes, object[] args)
        {
            EnsureTypes(objectType);
            if (objectType == _abstractType)
            {
                objectType = _concreteType;
            }

            return base.CreateInstance(provider, objectType, argTypes, args);
        }
    }
}

Weisen Sie sie auf Ihre abstrakten Form wie folgt aus:

[TypeDescriptionProvider(typeof(GeneralConcreteClassProvider))]
[ConcreteClass(typeof(MyAbstractConcreteForm))]
public abstract partial class MyAbstractForm : Form
{
}

Erstellen Sie eine neue Klasse, die von Ihrer abstrakten Form erben. Diese Klasse wird von Visual Studio instanziiert werden

public class MyAbstractConcreteForm: MyAbstractForm 
{
    public MyAbstractConcreteForm() : base() { }
}

Das sollte funktionieren.

Ich habe das gleiche Problem.
Diese Seite kann Ihnen helfen, auch wenn es nur eine Abhilfe ist: ein Formular von einer abstrakten Vererben Klasse (und machen es in Designer arbeiten) .

Ich habe keine bessere Lösung gefunden, aber es scheint, gibt es nicht. So in die Tat der Windows Forms Designer zwingen Sie Ihre Klasse Design anzupassen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top