2011-02-02 22 views
6

Perdón por el título estúpido, no tenía idea de cómo decir estoC#: Implementación de dos listas abstractas dentro de una clase no genérica?

Estoy creando una clase que tiene dos listas del mismo tipo. Se usa para copiar una referencia a un objeto en la primera lista a la segunda lista.

Aunque ambas listas serán del mismo tipo (mantienen el mismo tipo de objeto), pueden ser diferentes cada vez que se inicializa esta clase.

Así que supongo que debería hacer los tipos de lista como un tipo de lista de resumen. Me gustaría asegurarme de que se escribirán fuertemente cuando se haga la instancia (pero no es necesario si es problemático). El problema está en el método que mueve los elementos seleccionados de la lista1 a la lista2. Los tipos de listas abstractas normalmente no tienen métodos para eso.

Supongo que la solución normal sería hacer que la clase sea genérica (className <T> thingy) pero no estoy seguro de poder hacerlo (al menos no sé cómo) porque esta clase hereda un UserControl de WPF.

Aquí está el código:

public partial class SubsetSelectionLists : UserControl 
{ 
    public static DependencyProperty SetCollectionProperty = DependencyProperty.Register("SetCollection", typeof("Need a abstract list type here"), typeof(SubsetSelectionLists)); 
    public static DependencyProperty SubsetCollectionProperty = DependencyProperty.Register("SubsetCollection", typeof("Need a abstract list type here"), typeof(SubsetSelectionLists)); 

    public "Need a abstract list type here" SetCollection 
    { 
     get 
     { 
      return ("Need a abstract list type here") GetValue(SetCollectionProperty); 
     } 
     set 
     { 
      SetValue(SetCollectionProperty, value); 
     } 
    } 

    public "Need a abstract list type here" SubsetCollection 
    { 
     get 
     { 
      return ("Need a abstract list type here")GetValue(SubsetCollectionProperty); 
     } 
     set 
     { 
      SetValue(SubsetCollectionProperty, value); 
     } 
    } 

    public SubsetSelectionLists() 
    { 
     InitializeComponent(); 
     SubsetSelectiongrid.DataContext = this; 
    } 

    private void selectionBtnClick(object sender, RoutedEventArgs e) 
    { 
     SubsetCollection.AddTheseItems(SET.SelecctedItems) 
    } 

    private void removeBtnClick(object sender, RoutedEventArgs e) 
    { 
     SUBSET.RemoveTheseItems(SUBSET.SelectedItem); 
    } 
} 

EDIT: Solución

Algunas respuestas me apuntaban hacia la solución óptima de la creación de una clase genérica. Sin embargo, esto puede ser problemático en WPF. Tendría que omitir el XAML en la clase genérica de nivel superior.

Esto significa que podría hacer el XAML en el tipo de clases secundarias específicas que no es algo que le gustaría hacer (a menos que solo el código sea algo que pueda volver a usar pero el aspecto sea variable). También podría haber diseñado el control utilizando el código, supongo, pero no estoy seguro de cuán efectivo sería.

Me apuntaron hacia el objeto IList que es una lista abstracta de la que muchos otros heredarán y que voy a usar. Es un truco, pero como esto no se usará en una biblioteca abierta, estoy de acuerdo. De lo contrario, usaría la ruta genérica.

+0

¿Por qué razón no puedes hacerlo en linq? ¿tienes limitaciones en tu versión de .net? – phillip

+0

Qué versión .net. Linq y genéricos deberían poder hacer eso – Hawxby

+2

No entiendo cómo linq podría ayudarme aquí? Por favor, envíe una respuesta de cómo se hace. Estoy usando .net 3.5 pero probablemente me actualizaré a 4.0 –

Respuesta

3

No sé qué tan bien juegan los diseñadores con controles de usuario que son clases genéricas.Si eso es un problema (lo que supongo), una forma de evitarlo es exponer las colecciones IList pero aún usar List<T> que están construidas en tiempo de ejecución para tener seguridad de tipo en el almacenamiento (muestra de código reducida para incluir solo el objeto de lista) creación y propiedades para exponerlos; agregan código para DependencyProperty, etc., según sea necesario):

public class YourControl : UserControl 
{ 

    // this method will set up the internal lists for accepting 
    // objects of the specified type only 
    public void SetListType(Type containedType) 
    { 
     var listType = typeof(List<>).MakeGenericType(new[] { containedType }); 
     SetCollection = (IList)Activator.CreateInstance(listType); 
     SubsetCollection = (IList)Activator.CreateInstance(listType); 
    } 
    public IList SetCollection { get; private set; } 
    public IList SubsetCollection { get; private set; } 
} 

// usage example: 
theControl.SetListType(typeof(string)); 
theControl.SetCollection.Add("some string"); // works ok 
theControl.SetCollection.Add(42); // fails, 42 is not a string 

La desventaja obvia es que SetCollection y SubsetCollection exponga "sin tipo" object listas.

+0

Ok, este fue útil. Puedo usar IList porque implementa el método Add. Acabo de poner IList en todas partes donde dice "Necesito un tipo de lista abstracta aquí" y luego me aseguro de vincular una lista (ObservableCollection en mi caso) que hereda IList. Cada lista será segura, pero no me aseguro de que tengan el mismo tipo. –

2

Como dices, una clase genérica es la forma de lograr esto y puedes hacerlo al heredar de una clase primaria no genérica, p. Ej.

partial class GenericClass1<T> : UserControl 
    { 
    private List<T> _list; 
    } 

EDITAR basado en los comentarios a continuación

definir clases con tipo que fijan el tipo genérico de la clase anterior (y pueden ser utilizados por el diseñador), es decir

partial class IntClass1 : GenericClass1<int> {} 

partial class StringClass1 : GenericClass1<string> {} 

.... 

Por supuesto esto realmente solo funciona si tiene un conjunto limitado/estático de tipos que desea mantener en sus listas

+0

Siempre que el elemento primario no genérico no sea una clase WPF UserControl. Traté de hacer esto, noto que es una clase parcial y el resto de la clase se declara en XAML. Encontré una publicación que decía que no puedes hacer controles de usuario genéricos. –

+0

Una vez que haya definido su clase genérica, ¿no podrá entonces definir las subclases tipadas que funcionarán como controles de usuario de WPF? –

+0

El problema es que no puedo definir la otra mitad del parcial como genérica, es decir, el código que está en XAML. La clase simplemente no compilaría. Podría crear la clase sin la parte XAML pero luego tendría que diseñar la apariencia (que sería la misma en todas las subclases también) en el código o en todas las subclases que no quiero que suceda. Estoy marcando tu publicación como útil. –

3

Algo como esto o soy sh lanzando una gran parte de la marca?

public partial class SubsetSelectionLists<T> : UserControl 
{ 
    public List<T> SetCollection { get; set; } 

    public List<T> SubsetCollection { get; set; } 

    public SubsetSelectionLists() 
    { 
     SubsetSelectiongrid.DataContext = this; 
    } 

    private void selectionBtnClick(object sender, RoutedEventArgs e) 
    { 
     SubsetCollection.AddRange(SetCollection); 
    } 

    private void removeBtnClick(object sender, RoutedEventArgs e) 
    { 
     SubsetCollection.RemoveAll(x => SetCollection.Contains(x)); 
    } 
} 
+0

Bueno, como dije en mi pregunta, así es como normalmente se haría. Sin embargo, como hereda de un WPF userControl, no parece funcionar. –

+0

Marcaría la clase como abstracta y luego crearía clases de control que heredarían de ella para que pueda especificar un tipo. – Hawxby

+0

Todavía necesitaría heredar la clase UserControl originalmente y esto me aseguraría que tendría que omitir el código XAML y diseñar el aspecto en el código o en cada elemento secundario (que es lo que estoy tratando de evitar en primer lugar). Podría usar tu camino si omito la parte parcial e ignoro el XAML así que te estoy dando un voto útil. –

Cuestiones relacionadas