我有一个ObservableCollection绑定到WPF中的ListBox。我希望ListBox可以编辑,并将编辑更改保存到集合中。由于WPF不提供可编辑的列表框,我尝试通过更改ListBox.ItemTemplate来创建自己的列表框。
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="EditableText" Text="{TemplateBinding Content}"/>
</DataTemplate>
</ListBox.ItemTemplate>
更改ItemTemplate会为我提供可编辑的框,但对文本框的任何更改都不会保存到ObservableCollection中。有没有办法让可编辑的ListBox具有双向绑定?
答案 0 :(得分: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)已加载,并且项目(我假设是您的情况下的字符串)将被传入。 此时,它只知道字符串,不能向上影响任何东西。双向绑定不能影响集合,因为模板不知道它在哪个上下文中使用,因此它无法返回到原始集合并修改其内容。 就此而言,TextBox也是如此。如果没有给出变量和属性名称,则无法“存储”更改。 这与将字符串传递给函数调用基本相同。该函数无法更改传入的字符串(忽略诸如by-reference参数传递之类的技巧)。
要回到您的案例,您需要构建一个对象集合,这些对象公开包含需要编辑的值的属性:
public class MyDataItem
{
string Data { get; set;}
}
然后,您可以将ListBox绑定到这些项的集合并修改您的datatemplate:
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Name="EditableText" Text="{Binding Data, Mode=TwoWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
答案 1 :(得分:0)
绑定到模型属性(即数据对象的属性),而不是绑定到视图属性(如Content)。例如:
// model class
public class Widget : INotifyPropertyChanged
{
public string Description { ... }
}
<!-- view -->
<DataTemplate>
<TextBox Text="{Binding Description}" />
</DataTemplate>
注意,如果您的ItemsSource是ObservableCollection(因为没有要绑定的属性),这将不起作用。