wpf - ¿Por qué CompositeCollection no es Freezable?
(1)
Acabo de intentar esto esta noche:
public class State
{
public string Code { get; set; }
public string Name { get; set; }
}
public class MyWindowViewModel
{
ObservableCollection<State> _states = new ObservableCollection<State>
{
new State { Code = "FL", Name = "Florida" },
new State { Code = "CA", Name = "California" },
};
public ObservableCollection<State> States
{
get
{
return _states;
}
}
}
<Window x:Class="WpfApplication1.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:WpfApplication1"
Title="Window1"
Height="300"
Width="300">
<Window.Resources>
<app:ServiceLocator x:Key="Locator" />
</Window.Resources>
<StackPanel>
<ComboBox x:Name="TestCombo" SelectedIndex="0" DisplayMemberPath="Name" SelectedValuePath="Code">
<ComboBox.ItemsSource>
<CompositeCollection>
<app:State Code="" Name="Select a state..." />
<app:State Code="TX" Name="Texas" />
<CollectionContainer Collection="{Binding Source={StaticResource Locator}, Path=MyWindowViewModel.States}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
</StackPanel>
</Window>
La clave aquí es crear una instancia de su localizador de servicios como un recurso estático y luego examinarla para llegar a su modelo de vista. El localizador de servicios puede conectarse a instancias de ViewModel utilizando Unity o cualquier DI que desee.
Editar:
En realidad, en mi aplicación de Silverlight creo el localizador de servicios como un recurso estático en App.xaml y luego ajusto mis otros UserControls / Windows / Pages DataContext a una propiedad ViewModel del localizador de servicios. Aún debería funcionar de la misma manera para los cuadros combinados, aunque incluso si el localizador de servicios se crea una instancia en los recursos de App.xaml. Me gustaría que hubiera una versión Silverlight de CompositeCollection que pudiera usar. Esto funcionaría muy bien para la aplicación en la que estoy trabajando. :(
Estoy escribiendo una aplicación usando el patrón MVVM. Estoy proporcionando datos a mi vista configurando la propiedad DataContext de mi vista en una instancia de mi ViewModel. Generalmente solo uso Binding desde allí y voy por mi camino.
Recientemente, intenté implementar un ComboBox con un elemento "extra" más allá de la colección que mi ViewModel proporciona que dice "Seleccionar elemento".
<ComboBox>
<ComboBox.ItemsSource>
<CompositeCollection>
<ComboBoxItem IsEnabled="False">Select Item</ComboBoxItem>
<CollectionContainer Collection="{Binding MyItemsCollection}" />
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
El problema es que CompositeCollection no es Freezable: Información general de objetos Freezable . Esto hace que solo aparezca el ComboBoxItem estático y ninguno de los resultados de mi expresión de enlace.
Mi primera reacción al problema fue simplemente implementar mi propia versión de CompositeCollection que era Freezable. Esto, sin embargo, plantea la siguiente pregunta:
¿Por qué no es CompositeCollection un Freezable en primer lugar?
Mi preocupación es que, en general, estas decisiones se toman por una razón y no creo que sepa lo suficiente sobre Freezable para decir por qué no se heredaron de ella. Sé que puedo implementar esta colección, pero me preocupa que habrá una diferencia apreciable en el rendimiento si lo hago.
Cualquier ayuda sería apreciada. ¡Gracias!
También: tenga en cuenta que me doy cuenta de que puedo insertar un valor nulo o algún otro valor especial y proporcionar una plantilla o un valueconverter para hacer lo que quiero. Esta no es la pregunta que me interesa ... solo la pregunta en negrita de arriba.
Actualizar:
Después de algunas investigaciones adicionales provocadas por el comentario de ArsenMkrt, me hacen creer que esto fue en realidad un descuido. La evidencia es esta:
- Hay una colección que es freezable llamada
FreezableCollection<T>
. No produzco CollectionViews, lo que lo hace inadecuado para mis necesidades directamente. - Sam Bent de MSFT lo dice en el enlace de arriba. Todavía no puedo encontrar información de contacto para él, pero planeo discutir esto con él si tengo la oportunidad.
Mi plan actual para solucionar este problema es crear una nueva colección con las propiedades de CompositeCollection y FreezableCollection<T>
. No sé si funcionará todavía, pero estoy pensando en algo como esto:
public class BindableCompositeCollection : FreezableCollection<object>, ICollectionViewFactory
¡Si alguien tiene una opción mejor, me gustaría escucharla!