2009-05-14 5 views
8

legata alla mia domanda precedente: Binding ComboBox.SelectedItem in SilverlightBinding ComboBox.SelectedItem in Silverlight (più)

Ho un ComboBox legata in questo modo:

<ComboBox x:Name="PART_CommentaryList" 
    HorizontalAlignment="Left" 
    Margin="3" 
    ItemsSource="{Binding Path=CurrentVideo.Commentaries}" 
    SelectedItem="{Binding Path=CurrentCommentary, Mode=TwoWay}"> 

Sia il CurrentVideo e il cambiamento di proprietà CurrentCommentary regolarmente. Dopo alcune volte, ho ricevuto questo errore:

Category: ManagedRuntimeError  
Message: System.ArgumentException: Value does not fall within the expected 
    range. 
    at MS.Internal.XcpImports.MethodEx(IntPtr ptr, String name, 
     CValue[] cvData) 
    at MS.Internal.XcpImports.MethodPack(IntPtr objectPtr, String methodName, 
     Object[] rawData) 
    at MS.Internal.XcpImports.UIElement_TransformToVisual(UIElement element, 
     UIElement visual) 
    at System.Windows.UIElement.TransformToVisual(UIElement visual) 
    at System.Windows.Controls.Primitives.Selector.IsOnCurrentPage(
     Int32 index, Rect& itemsHostRect, Rect& listBoxItemRect) 
    at System.Windows.Controls.Primitives.Selector.ScrollIntoView(
     Int32 index) 
    at System.Windows.Controls.Primitives.Selector.SetFocusedItem(
     Int32 index, Boolean scrollIntoView) 
    at System.Windows.Controls.ComboBox.PrepareContainerForItemOverride(
     DependencyObject element, Object item) 
    at System.Windows.Controls.ItemsControl.UpdateContainerForItem(
     Int32 index) 
    at System.Windows.Controls.ItemsControl.RecreateVisualChildren() 
    at System.Windows.Controls.ItemsControl.RecreateVisualChildren(
     IntPtr unmanagedObj) 

Questo mi sembra un bug di ComboBox. Posso verificare che CurrentVideo cambi prima di CurrentCommentary, quindi l'elemento selezionato dovrebbe sempre essere un elemento presente nell'elenco.

Correlato, non desidero davvero il Modo = DueWay, perché quando si seleziona ItemsSource, il SelectedItem è temporaneamente nullo, che viene reimpostato nel mio modello, che in realtà non desidero. Ma il binding non funziona affatto (il che sembra un altro bug).

+0

Stai verificando che CurrentCommentary sia ancora nell'elenco CurrentVideo.Commentaries, perché se non lo è, otterrai questo errore. –

+0

Ho iniettato un convertitore in entrambe le proprietà associate per verificare se l'elemento selezionato si trova effettivamente nell'origine articoli. Il problema sembra essere: ItemsSource cambia. Tale modifica fa sì che SelectedItem diventi nullo. SelectedCommentary cambia in null perché è un binding a due vie. SelectedCommentary è impostato sul valore appropriato dall'app, questo valore è sicuramente all'interno di ItemsSource. Errore succede. Se la modalità di rilegatura non è TwoWay, non c'è errore, ma la voce corretta non viene mai selezionata. –

risposta

0

Combobox è un controllo di SL buggy abbastanza :-(

Nel mio caso ho rinunciato con il legame del declarativa elemento selezionato e utilizzare l'approccio di codifica brutto ... brutto, ma funziona:.

http://blogs.msdn.com/mikehillberg/archive/2009/03/26/implementing-selectedvalue-with-the-silverlight-combobox.aspx

HTH Braulio

+0

Post interessante, ma questo non sembra davvero rilevante per il mio problema. Ho imparato a conoscere DisplayMemberPath, però. In precedenza avrei impostato un nuovo DataTemplate solo per visualizzare una proprietà dell'elemento. –

0

mi è stato sempre lo stesso problema qualche tempo fa e da quello che posso dire che è un bug nel ComboBox quando l'ItemSource viene modificato ha un problema con il layout e sc rotola male.

È possibile aggirare il problema chiamando ComboBox.UpdateLayout tra l'impostazione di ItemSource e SelectedItem.

Ho bloggato circa il problema qualche tempo fa a Gotcha when databinding a ComboBox in Silverlight.

Ho ancora per verificare se il problema esiste ancora nel Silverlight 3 Beta

+0

Utilizzare UpdateLayout è un buon approccio, ma ho dato un colpo e ancora finito con lo stesso errore. Ho capito quando si imposta SelectedItem nel codice o tramite associazione. –

+0

Nell'esempio del blog si sta vincolando a una proprietà in cui il getter crea dinamicamente un nuovo OC in get. Ciò cambierà il puntatore utilizzato dal collegamento ItemsSource ogni volta che viene valutato. Un approccio più stabile sarebbe quello di dichiarare un OC e aggiungere elementi ad esso. Inoltre, costruendo dinamicamente un OC , non ha senso nemmeno usare un OC , si potrebbe anche usare un elenco . – markti

+0

D'accordo, alla fine mi sono trasferito in un modello come quello, tuttavia è ancora un bug da tenere d'occhio quando si cambiano le fonti degli oggetti. –

1

Grazie per i suggerimenti di cui sopra. Nella mia situazione sono in grado di andare per la "opzione nucleare", che è - ogni volta che l'elemento selezionato deve cambiare, distruggo completamente il ComboBox, ne creo uno nuovo e setto il suo SelectedItem appropriatamente.

Ridicolo, ma funziona.

13

Questo è un bug nel controllo ComboBox che ha a che fare con il puntatore che cambia del binding di ItemsSource. La soluzione che ho trovato è:

1) Legare sempre ItemsSource a una raccolta osservabile e non reimpostare mai il puntatore dell'OC.

<ComboBox ItemsSource="{Binding MyList}" SelectedItem="{Binding MyItem}" /> 

Bad:

MyList = new ObservableCollection(); 

Buono:

MyList.Clear(); 
MyList.AddRange(...); 

2) Set MyItem = null, prima di eliminare MyList

Nel tuo caso si modifica il riferimento della Lista ogni volta che si modifica CurrentView. Pertanto, se SelectedItem non è nullo, c'è un breve momento nel quale viene ripristinato l'oggetto ItemsSource, i componenti interni del ComboBox stanno tentando di individuare l'oggetto SelectedItem nel nuovo ItemsSource ma il vecchio oggetto non è lì.

+0

Grazie per questo suggerimento @markti. Ho avuto lo stesso errore nella mia app di Windows 8.1 Store e mi stava guidando per la terapia. Il fatto interessante è che ho appena usato lo stesso approccio che funziona perfettamente in una vista diversa, approccio in cui la mia ItemsSource di ComboBox è associata a un elenco <> e non a ObservableCollection. Farò meglio a tornare e cambiarlo anche lì. – Eddie