visual studio que puede programacion presentacion hacer ejemplos desventajas con animaciones wpf listbox checkbox

que - visual studio wpf



¿Cómo implementar un ListBox de casillas de verificación en WPF? (5)

Aunque algo experimentado con la escritura de aplicaciones de Winforms, la ... "vaguedad" de WPF todavía me escapa en términos de mejores prácticas y patrones de diseño.

A pesar de llenar mi lista en tiempo de ejecución, mi listbox aparece vacío.

He seguido las sencillas instrucciones de este útil artículo sin resultado. Sospecho que me falta algún tipo de método DataBind() donde le digo a la lista que he terminado de modificar la lista subyacente.

En mi MainWindow.xaml, tengo:

<ListBox ItemsSource="{Binding TopicList}" Height="177" HorizontalAlignment="Left" Margin="15,173,0,0" Name="listTopics" VerticalAlignment="Top" Width="236" Background="#0B000000"> <ListBox.ItemTemplate> <HierarchicalDataTemplate> <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/> </HierarchicalDataTemplate> </ListBox.ItemTemplate> </ListBox>

En mi código subyacente, tengo:

private void InitializeTopicList( MyDataContext context ) { List<Topic> topicList = ( from topic in context.Topics select topic ).ToList(); foreach ( Topic topic in topicList ) { CheckedListItem item = new CheckedListItem(); item.Name = topic.DisplayName; item.ID = topic.ID; TopicList.Add( item ); } }

Lo cual, al rastrearlo, sé que está siendo poblado con cuatro elementos.

EDITAR

Cambié TopicList a ObservableCollection . Todavía no funciona.

public ObservableCollection<CheckedListItem> TopicList;

EDIT # 2

He hecho dos cambios que me ayudan:

En el archivo .xaml:

ListBox ItemsSource="{Binding}"

En el código fuente después de poblar la lista:

listTopics.DataContext = TopicList;

Obtengo una lista, pero no actualiza automágicamente los estados de la casilla de verificación cuando los actualizo. Sospecho que un poco más de lectura de mi parte resolverá esto.


Otros ya han hecho sugerencias útiles (utilizar una colección observable para obtener una notificación de cambio de lista, hacer que la colección sea una propiedad en lugar de un campo). Aquí hay dos que no tienen:

1) Cuando tenga un problema con el enlace de datos, mire en la ventana Salida para asegurarse de que no está recibiendo ningún error vinculante. Puede pasar mucho tiempo tratando de solucionar el problema incorrecto si no lo hace.

2) Comprenda la función de notificación de cambio de rol en el enlace. Los cambios en su fuente de datos no pueden y no se propagarán a la IU a menos que la fuente de datos implemente la notificación de cambio. Hay dos formas de hacer esto para las propiedades normales: hacer que el origen de datos se derive de DependencyObject y convertir la propiedad enlazada en una propiedad de dependencia, o hacer que el origen de datos implemente INotifyPropertyChanged y generar el evento PropertyChanged cuando cambie el valor de la propiedad. Al vincular un ItemsControl a una colección, use una clase de colección que implemente INotifyCollectionChanged (como ObservableCollection<T> ), de modo que los cambios en los contenidos y el orden de la colección se propaguen al control enlazado. (Tenga en cuenta que si desea que los cambios en los elementos de la colección se propaguen a los controles encuadernados, esos elementos también deben implementar notificación de cambio).


Primero, no necesita una HeirarchicalDataTemplate para esto. Solo DataTemplate normal como Aaron ha dado es suficiente. Luego necesita crear una instancia de TopicList ObservableCollection en algún lugar dentro del constructor de la clase. lo que hace que la ObservableCollection viva incluso antes de agregar datos en ella. Y el sistema vinculante conoce la colección. Luego, cuando agrega cada tema / CheckedListItem, se mostrará automáticamente en la interfaz de usuario.

TopicList = new ObservableCollection<CheckedListItem>(); //This should happen only once private void InitializeTopicList( MyDataContext context ) { TopicList.Clear(); foreach ( Topic topic in topicList ) { CheckedListItem item = new CheckedListItem(); item.Name = topic.DisplayName; item.ID = topic.ID; TopicList.Add( item ); } }


Suponiendo que TopicList no es una ObservableCollection<T> por lo tanto, cuando agrega elementos, no se INotifyCollection ningún cambio en INotifyCollection para indicarle al motor de enlace que actualice el valor.

Cambie su TopicList a ObservableCollection<T> que resolverá el problema actual. También puede llenar la List<T> antes de tiempo y luego el enlace funcionará a través de OneWay; sin embargo, ObservableCollection<T> es un enfoque más robusto.

EDITAR:

Su TopicList necesita ser una propiedad y no una variable miembro; enlaces requieren propiedades. No necesita ser una DependencyProperty .

EDICION 2:

Modifique su ItemTemplate ya que no necesita ser una HierarchicalDataTemplate

<ListBox.ItemTemplate> <DataTemplate> <StackPanel> <CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate>


Utilice ObservableCollection<Topic> lugar de List<Topic>

Editar

implementa la interfaz INotifyCollectionChanged para que WPF sepa cuándo agrega / elimina / modifica elementos

Editar 2

Como configura TopicList en el código, debe ser una Propiedad de Dependencia, no un campo común

public ObservableCollection<CheckedListItem> TopicList { get { return (ObservableCollection<CheckedListItem>)GetValue(TopicListProperty); } set { SetValue(TopicListProperty, value); } } public static readonly DependencyProperty TopicListProperty = DependencyProperty.Register("TopicList", typeof(ObservableCollection<CheckedListItem>), typeof(MainWindow), new UIPropertyMetadata(null));

Editar 3

Para ver los cambios en los artículos

  1. implementar la interfaz INotifyPropertyChanged en CheckedListItem (cada setter debería llamar a PropertyChanged(this, new PropertyChangedEventArgs(<property name as string>)) evento PropertyChanged(this, new PropertyChangedEventArgs(<property name as string>)) )
  2. o deriva CheckedListItem de DependencyObject , y convierte Name , ID , IsChecked a propiedades de dependencia
  3. o actualícelos totalmente ( topicList[0] = new CheckedListItem() { Name = ..., ID = ... } )

cambia tu enlace a

<ListBox ItemsSource="{Binding Path=TopicList}"