2009-04-12 2 views
5

У меня есть ObservableCollection, связанный с ListBox в WPF. Я хочу, чтобы ListBox был доступен для редактирования, и чтобы изменения редактирования были сохранены в коллекции. Поскольку WPF не предоставляет редактируемый список, я попытался создать свой собственный, изменив ListBox.ItemTemplate.Редактируемый WPF ListBox

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

Изменение ItemTemplate дает мне редактируемые коробки, но любые изменения в текстовые поля не получают сохраняются в ObservableCollection. Есть ли способ иметь редактируемый ListBox с двухсторонней привязкой?

ответ

8

Вы не можете сделать это таким образом.

Для достижения такого трюка вам понадобятся, чтобы ваши предметы были «классами держателей», которые выставляют свойство, к которому вы можете привязать свое текстовое поле.

Чтобы понять это, представьте себе следующую псевдо последовательность вызовов:

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 
    } 
    } 
} 

Ваш шаблону (DataTemplate с ListBox) загружается и элемент (который я предполагаю, это строка в вашем случае) пропускается in. На данный момент он знает только строку и не может ничего влиять на нее. Двусторонняя привязка не может влиять на сбор, поскольку шаблон не знает, в каком контексте он используется, поэтому он не может вернуться к исходной коллекции и изменить ее содержимое. В этом отношении, это то же самое для TextBox. Если ему не дано имя контейнера и имя свойства, ему некуда «хранить» изменения. Это в основном то же самое, что передать строку в вызов функции. Функция не может изменить, какая строка была передана (игнорируя трюки, такие как передача аргументов по ссылке).

Чтобы вернуться к вашему делу, вы должны создать коллекцию объектов, которые обнажают свойство, содержащее значение, которое должно быть отредактировано:

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

Затем вы можете связать свой ListBox к коллекции тех, пунктов и modifiy вашей datatemplate:

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

У меня есть аналогичная проблема, но поскольку я очень новичок в WPF, я не знаю, как написать {Binding Data, Mode = TwoWay}, если у меня есть список строк и нет никакого действительного свойства, которое может быть связано –

+1

You не могу, вот в чем мой ответ ... Вам нужно взять список строк, создать список объектов, содержащих эти строки (каждый объект содержит одну строку, доступную через свойство), и отобразить этот дополнительный список в ListBox , –

0

Привязывает свойство модели, то есть свойство объекта данных, а не свойство вида, например Content. Например:

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

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

Примечание это не будет работать, если ваш ItemsSource является ObservableCollection (потому что нет никакой собственности, чтобы связываться).

+0

Я не думаю, что я могу привязать текст текстового поля к объекту данных напрямую. В вашем примере вы привязываетесь к одной строке, но мой класс имеет их коллекцию, я не могу установить текстовое свойство в список строк. –

+0

DataTemplate повторяется для каждого элемента коллекции Items, с привязкой к этому члену. – itowlson