将ListView中ICollection <t>的当前上下文绑定到组合框</t>

时间:2011-04-12 01:57:45

标签: wpf data-binding listview binding

背景

我需要允许用户编辑IList<Move> moves,其中Move是不可变类。用户从下拉列表中选择移动(ComboBox)。例如:

[[ for every move slot ]]
    <ComboBox DisplayMemberPath="Name" ItemsSource="{DynamicResource MoveCollection}" SelectedValue="[[ move of the move slot ]]" />
[[ end for ]]

我的方法

我使用ListView来迭代集合,使用DataTemplate来创建ComboBox个实例,如下所示:

<ListView ItemsSource="{Binding Moves}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ComboBox DisplayMemberPath="Name" ItemsSource="{DynamicResource MoveCollection}" SelectedValue="{Binding}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

我得到一个例外(“双向绑定需要Path或XPath。”),所以我使用SelectedValue的以下绑定表达式:

{Binding Path=DataContext, RelativeSource={RelativeSource Self}}

这使它编译并运行。但是,moves集合不会在用户进行更改时更新。显然,只有数据上下文被改变,而不是实际值。

我认为这是一个问题,因为IList<Move>被WPF简单地视为只读集合,并且对组合框值的更改不会也不能修改该集合。在代码中,WPF无法执行以下操作:

moves[x] = Resources["MoveCollection"][y];

我想更改组合框的值以更新moves集合。我怎么能做到这一点?

1 个答案:

答案 0 :(得分:0)

是的,您对IList的怀疑是部分正确的。让我们来看看幕后真正发生的事情: ListView是一个项目集合。对于每个项目,它会在面板模板指定的面板中创建数据模板的新副本。数据模板将作为其DataContext传递给它感兴趣的对象的引用。因此,即使您成功更改了值,基础方案在C#中也是如此:

列出yourItems = ...; foreach(yourItems中的字符串yourItem) {    someControl.DataContext = yourItem;

//你在这里改变它    someControl.DataContext = yourNewItem; }

您不希望上述代码更改列表。虽然它有点不同,但我认为这里发生的事情是相似的。

我认为做你想做的最简单的方法就是做一个IList&gt;。 Wrapper只是一个包含Move的虚拟类。绑定将改变包装器上的Move。在后端,当你需要一个LINQ时,打开列表是微不足道的。

那声音怎么样?