2010-04-29 12 views
8

Quiero vincular Listbox selectedItems a la matriz. Pero .NET lanza una excepción en el tiempo de ejecución.ListBox SelectedItems Enlace

d.SetBinding(ListBox.SelectedItemsProperty, new Binding { Source = SomeArray }); 

Dónde d es un poco de cuadro de lista de XAML.

Excepción:

elemento seleccionado no puede ser obligado.

¿Por qué?

Respuesta

1

ListBox.SelectedItems es de solo lectura. ¿Querías enlazar al ListBox.SelectedItem?

+0

No tengo varios elementos seleccionados y quiero mostrarlas en ListBox en estado seleccionado – Polaris

+1

Dado que la propiedad es de sólo lectura, no se puede utilizar para lo que querer. Lo único que se me ocurre es establecer propiedades individuales 'ListBoxItem.IsSelected'. Si insiste en la vinculación, la ruta más fácil sería crear, p. un SelectedItems adjuntado 'DependencyProperty' con lógica personalizada en el controlador de eventos modificado por evento. – wpfwannabe

1

No estoy seguro si entiendo su pregunta correctamente o el escenario exacto, pero suponiendo que deseara tener una lista "d" para mostrar los elementos que se seleccionaron en otra lista de lista "MyOtherListbox", solo tiene que establecer la vinculación modo a 'unidireccional' de lo contrario, aparecerá un error.

Se podría hacer algo como

d.SetBinding(ListBox.ItemsSourceProperty, new Binding { Source = MyOtherListbox.SelectedItems, Mode = BindingMode.OneWay}); 
+0

Debo usar algo como esto: d.SetBinding (ListBox.SelectedItemsProperty, nueva vinculación {Source = SomeArray, Mode = OneWay}); Pero plantea la misma excepción. – Polaris

+1

No, no puede vincularse a la propiedad SelectedItems porque solo tiene un acceso get. Creo que lo más cercano que obtendrá es si lee el siguiente hilo ... http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/f0183ef3-ee0e-4de9 -86c7-73d2072baba7 –

+0

gran hilo. Funciona como espero. – Polaris

7

Usted puede suscribirse al evento SelectionChanged del cuadro de lista, y en el manipulador de sincronización de una colección de elementos seleccionados.

En este ejemplo, el DataContext de Windows se configuró a sí mismo (esto) en su constructor. También puede llamar fácilmente a una capa lógica (ViewModel si usa MVVM) desde el controlador de eventos.

en XAML:

<StackPanel> 

    <ListBox 
     ItemsSource="{Binding ListBoxItems}" 
     SelectionMode="Multiple" 
     SelectionChanged="ListBox_SelectionChanged"> 
    </ListBox> 

    <ItemsControl 
     ItemsSource="{Binding SelectedItems}"> 
    </ItemsControl> 

</StackPanel> 

Y en el código subyacente:

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    foreach (string item in e.RemovedItems) 
    { 
     SelectedItems.Remove(item); 
    } 

    foreach (string item in e.AddedItems) 
    { 
     SelectedItems.Add(item); 
    } 
} 
+2

Esto parece funcionar como enlace de OneWayToSource. Si cambio la colección SelectedItems, los cambios no se reflejan en el cuadro de lista. –

+1

@BogdanVerbenets Tal vez configurar Modo a TwoWay y UpdateSourceTrigger a PropertyChanged hará el truco? Por cierto, ¡tenemos el mismo nombre! : D –

+2

Downvoted porque sugerir el uso de un controlador de eventos en código subyacente para llamar a un modelo de vista no sigue el patrón MVVM. Si no te importa el código subyacente (y me importa, pero lo que sea), utiliza esto. Pero, por favor, no contamine a los modelos llamándolos desde el código subyacente. – aaronburro

3

Esta es la solución de trabajo, sin embargo, cuando la selección cambia SelectedItemsProperty no se actualiza encuadernaciones ...

puede crear un control personalizado de la siguiente manera

public class MyListBox: ListBox{ 

    public MyListBox() 
    { 
     this.SelectionChanged += (s,e)=>{ RefreshBindings(); }; 
    } 

    private void RefreshBindings() 
    { 
     BindingExpression be = 
      (BindingExpression) GetBindingExpression(
             SelectedItemsProperty); 
     if(be!=null){ 
       bd.UpdateTarget(); 
     } 
    } 

} 

o en su aplicación se puede definir evento en cada cuadro de lista como se muestra a continuación ..

myListBox.SelectionChanged += (s,e) => { 
    BindingExpression be = 
     (BindingExpression) myListBox.GetBindingExpression(
             ListBox.SelectedItemsProperty); 
    if(be!=null){ 
     bd.UpdateTarget(); 
    } 
}; 
+0

gracias. Agregué una solución en mi respuesta – dovid

0

mi truco: en XAML, utilice MultiBinding, fuerza ejecutar convertidor de Count cambio de propiedad (que funcione!).

<MultiBinding Converter="{StaticResource SelectedRowsTotal }"> 
    <Binding Path="SelectedItems" ElementName="listBox1" /> 
    <Binding Path="SelectedItems.Count" ElementName="listBox1" /> 
</MultiBinding> 

Convertidor:

public class SelectedRowsTotal : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var selecteds = values as IEnumerable; 

     if (selected == null) 
      return null; 

     return selecteds.Cast<SomeType>().Sum(x=> x.SomeProperty) = total; 
    } 

    object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     return null; 
    } 
} 
Cuestiones relacionadas