Newsgroup: it.comp.dotnet
Titolo: [WPF] Refresh combobox forzato non funziona

Ciao a tutti.
Ho questa situazione:
Lato DataContext:
         private List<string> _fieldList;
         public List<string> FieldList
         {
             get
             {
                 _fieldList.Clear();
                 FillFieldList();
                 return _fieldList;
             }
             set
             {
                 _fieldList = value;
                 OnPropertyChanged("FieldList");
             }
         }
[...]
         private void FillFieldList()
         {
             _fieldList.Add("Previous block");
             foreach (IBlock b in this.Scope.BlockSet)
             {
                 _fieldList.Add(b.Name);
             }
         }
e una combobox che gli si "binda":
     <ControlTemplate x:Key="ComboBoxContentControl" >
         <ComboBox
             x:Name="FieldComboBox"
             Margin="1"
             Padding="1"
             Background="{x:Null}"
             ItemsSource="{Binding Path=FieldList, Mode=OneWay}"
             SelectionChanged="selectionChangedHandler"
             ButtonBase.Click="cbButtonClicked"
             SelectedIndex="{Binding Path=SelectedIndex, Mode=OneTime}">
         </ComboBox>
     </ControlTemplate>
con "cbButtonClicked" voglio forzare una rilettura del Source del 
binding, perché alcune operazioni in altri componenti possono modificare 
la condizione su Scope.BlockSet(vedi sopra).
A tale scopo:
         void cbButtonClicked(object sender, RoutedEventArgs e)
         {
             ComboBox cb = sender as ComboBox;
             if (cb != null)
             {
                 BindingExpression be = 
cb.GetBindingExpression(ComboBox.ItemsSourceProperty);
                 be.UpdateTarget();
             }
         }
Ciò mi scatena correttamente la rilettura del get di FieldList, che 
viene correttamente aggiornata (per esempio, passa da 2 a 3 elementi) ma 
la combobox, quando si apre, mostra sempre i 2 elementi precedenti.
Cos'è che non riesco a vedere? Non vorrei farvi perdere tempo, e ho 
l'impressione che sia una boiata, ma a quest'ora e con due sole ore di 
sonno alle spalle, sono decisamente in panne...

 alle spalle, sono decisamente in panne...
a naso mi viene da pensare che il motore di data binding sia smart e si 
accorda che la reference non è cambiata ergo ignora la cosa, del resto 
la "list" è sempre quella. Se così fosse mi viene una domanda: ma 
perchè quel codice così farraginoso? se usassi una 
ObservableCollection<String> avresti tutto gratis al volo, inoltre 
perchè esposse il "setter" della list come pubblico?
.m
-- 
Mauro Servienti
{C67C0157-5D98-4733-A75E-93CAEE4BADC8}
Microsoft MVP - Visual C# / MCTS
http://mvp.support.microsoft.com/profile/mauro
blog @ 
http://milestone.topics.it
whynot [ at ] topics [ dot ] it

 list come pubblico?
Sei meglio di Wolf in Pulp Fiction...
così va meglio:
         private ObservableCollection<string> _fieldList;
         public ObservableCollection<string> FieldList
         {
             get
             {
                 _fieldList.Clear();
                 FillFieldList();
                 return _fieldList;
             }
         }
il setter non serviva proprio (e giulio da tempo cerca invano di levarmi 
il vizio di mettere il setter pubblico "a prescindere") ma onestamente 
non capisco il perché di quel comportamento precedente, o meglio, credo 
di capire che dichiarare la privata _fieldList come ObservableCollection 
mi dà la notifica propertychanged già inclusa (e mi sembra anche la 
collectionchanged, o sbaglio?) dunque quando agisco "privatamente" 
facendo add, clear, e quant'altro ho tutta una serie di notifiche che 
col caso precedente non avevo.
Comunque, grazie 1000

 avevo.
La notifypropertychanged no e se la vuoi devi sempre spararla tu quando 
rimpiazzi il reference della collection.
Le notifiche interne alla collection (add, remove, insert) invece le 
spara la observablecollection.
Se la tua collection è immutabile, la observable non ti serve a nulla.
Se l'istanza della tua collection è sempre la stessa per tutta la 
durata del VM, la notifypropertychanged non ti serve a nulla.
-- 
Raffaele Rialdi  
http://www.iamraf.net
Weblog: 
http://blogs.ugidotnet.org/raffaele
Microsoft MVP profile 
https://mvp.support.microsoft.com/profile/raffaele
UGIdotNET - 
http://www.ugidotnet.org/

 ma onestamente non capisco il perché di quel comportamento precedente
il motore di data binding fa questo ragionamento: tu gli dai una 
reference, poi gli dici di fare l'update, ma lui dice la reference non 
è cabiata perchè mai devo sprecare tempo a fare l'update? lui non ha la 
più pallida idea che la reference internamente sia diversa, l'unica 
cosa che può fare è un ReferenceEquals con quello che ha in mano.


 del VM, la notifypropertychanged non ti serve a nulla.
il caso è infatti questo, lavoro sulla stessa collection che viene 
svuotata/riempita alla bisogna, quello che ancora non mi è chiaro 
(nonostante adesso con la observablecollection funzioni) è perché la 
combobox, opportunamente "titillata" con 
cb.GetBindingExpression(ComboBox.ItemsSourceProperty).UpdateTarget();
faceva riscattare il get della property bindata, aggiornava il numero di 
items ma non aggiornava il numero degli elementi visuali.
Forse come diceva Mauro quando il binding è su una property "normale" 
(List) c'è un accoppiamento "smart" che non vedendo cambio di reference 
non aggiorna il componente, e forse dotando la property di un gestore 
della collectionchanged la cosa poteva funzionare. Per ora sono 
soddisfatto così, poi se ho cinque minuti faccio la prova.
Grazie

 poi se ho cinque minuti faccio la prova.
ok, ma in ogni caso non ci sono magie. Ci vuole un evento che notifichi 
alla view di aggiornare gli item
