2009-04-12 11 views
5

Ho una ObservableCollection associata a un ListBox in WPF. Voglio che il ListBox sia modificabile e che le modifiche di modifica vengano salvate nella raccolta. Dal momento che WPF non fornisce una listbox modificabile, ho provato a crearne uno cambiando il ListBox.ItemTemplate.ListBox WPF modificabile

<ListBox.ItemTemplate> 
    <DataTemplate>      
     <TextBox Name="EditableText" Text="{TemplateBinding Content}"/> 
    </DataTemplate> 
</ListBox.ItemTemplate> 

Modifica del ItemTemplate mi dà scatole modificabili, ma eventuali modifiche alle caselle di testo non si ottengono salvati nella ObservableCollection. C'è un modo per avere un ListBox modificabile con binding a due vie?

risposta

8

Non puoi farlo in questo modo.

Per ottenere questo tipo di trucco, i tuoi articoli devono essere "classi di titolari" che espongono una proprietà a cui puoi associare la tua casella di testo.

per capirlo, immaginare la seguente sequenza pseudo di chiamate:

class ListBox 
{ 
    Bind(Items) 
    { 
    foreach(var item in Items) 
    { 
     DataTemplate Template = LoadTemplateForItem(item.GetType()); // this is where your template get loaded 
     Template.Bind(item); //this is where your template gets bound 
    } 
    } 
} 

Il modello (DataTemplate con la casella di riepilogo) viene caricato e l'oggetto (che presumo è una stringa nel tuo caso) viene superato A questo punto, conosce solo la stringa e non può influenzare nulla verso l'alto. Un'associazione bidirezionale non può influenzare la raccolta perché il modello non sa in quale contesto viene utilizzato, quindi non può raggiungere la raccolta originale e modificarne il contenuto. Per questo, questa è la stessa cosa per il TextBox. Se non viene fornito un conainer e un nome di proprietà, non ha alcun luogo per "memorizzare" le modifiche. Fondamentalmente è come passare una stringa in una chiamata di funzione. La funzione non può cambiare quale stringa è stata passata (ignorando trucchi come passare per argomento di riferimento).

Per tornare al vostro caso, è necessario costruire una collezione di oggetti che espongono una proprietà che contiene il valore che deve essere modificato:

public class MyDataItem 
{ 
    string Data { get; set;} 
} 

Quindi è possibile vincolare il proprio ListBox a una raccolta di quelli articoli e modificare il datatemplate:

<ListBox.ItemTemplate> 
    <DataTemplate>            
      <TextBox Name="EditableText" Text="{Binding Data, Mode=TwoWay}"/> 
    </DataTemplate> 
</ListBox.ItemTemplate> 
+0

Ho un problema simile, ma poiché sono molto nuovo con WPF non so come scrivere {Binding Data, Mode = TwoWay} se ho una lista di stringhe e non ci sono proprietà reali che possono essere associate a –

+1

impossibile, questo è il punto della mia risposta ... È necessario prendere l'elenco delle stringhe, creare un elenco di oggetti contenenti tali stringhe (ogni oggetto contiene una stringa, accessibile tramite una proprietà) e visualizzare quell'elenco secondario in ListBox . –

0

Associare a una proprietà del modello, ad esempio una proprietà dell'oggetto dati, anziché a una proprietà vista come Contenuto. Per esempio:

// model class 
public class Widget : INotifyPropertyChanged 
{ 
    public string Description { ... } 
} 

<!-- view --> 
<DataTemplate> 
    <TextBox Text="{Binding Description}" /> 
</DataTemplate> 

Nota questo non funzionerà se il vostro ItemsSource è ObservableCollection (perché non c'è alcuna proprietà di legarsi a).

+0

Non penso di poter collegare direttamente il testo della casella di testo all'oggetto dati. Nel tuo esempio ti leghi a una singola stringa, ma la mia classe ne ha una collezione, non posso impostare la proprietà Text in una lista di stringhe. –

+0

Il DataTemplate viene ripetuto per ciascun membro della raccolta Articoli, con il set di rilegature impostato su quel membro. – itowlson