ListBoxItem模板中的WPF/MVVM绑定复选框到SelectedItem属性

ListBoxItem模板中的WPF/MVVM绑定复选框到SelectedItem属性,wpf,mvvm,listbox,checkedlistbox,Wpf,Mvvm,Listbox,Checkedlistbox,我正在构建一个WPF应用程序.NET 4.0,我有以下情况: <ListBox ItemsSource="{Binding Path=Items}" SelectedItem="{Binding Path=SelectedItem}"> <ListBox.ItemContainerStyle> <Style TargetType="ListBoxItem"> <Setter Property

我正在构建一个WPF应用程序.NET 4.0,我有以下情况:

<ListBox
    ItemsSource="{Binding Path=Items}"
    SelectedItem="{Binding Path=SelectedItem}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Height" Value="48"/>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <DockPanel>
                <!-- ... -->
                <CheckBox>
                    <CheckBox.IsChecked>
                        <!-- Something here that behaves like SelectedItem binding -->
                    </CheckBox.IsChecked>
                </CheckBox>
            </DockPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
ListBox的ItemSource绑定到ObservableCollection。 ListBox的SelectedItem绑定到SelectedItem属性 视图模型的。 但是,更新ViewModel.SelectedItem时,会启动一些长时间运行的2-3s异步任务。 只需在列表框中选择不同的项,就很容易将大量异步任务排队,因此我正在研究将ViewModel.SelectedItem绑定到复选框,而不是包含在ItemTemplate中

我对WPF相当陌生,但在表单中,我会附加一个事件处理程序,并编写一些长而难看的代码来取消检查所有项目(触发事件的项目除外),然后以编程方式更新属性

在WPF中,我希望有更好的解决方案,我已经研究过使用ValueConverter,但是我不知道如何绑定到具有ObservableCollection的父视图模型

如果有人遇到过类似的需求,我会非常感激一些建议

干杯


./Fredrik

您好,您可以将复选框绑定到命令到VM,当选中/取消选中复选框时,命令将触发

您可以通过TemplateBinding将ListBoxItem的isselected属性绑定到复选框。

我想出了一个解决方案,它不需要在代码背后处理选中的状态,所以我将为后代记录它

第一个诀窍是使用RadioButton,与和关联的GroupName一起使用。同一组中的单选按钮将自动确保在任何给定时间只选中其中一个,从而避免手动管理选中状态的问题

第二个技巧是将CommandParameter绑定到单选按钮DataContext


通过反复单击复选框,将大量异步任务排队不是同样容易吗?我想您需要的是一种机制,当新任务启动时,它会取消当前正在运行的任务。你可以考虑做一个延迟启动的任务,而不是在选择的项目发生时立即执行它。嗨,克莱门斯,谢谢!是的,它会,但在异步任务运行时防止更改已检查状态应该不会太难。我也尝试过在任务运行时禁用列表框,但这太难看了。添加复选框的好处是,列表框内的选择与任务分开,允许用户在任务运行时浏览列表框。您还可以考虑在列表框外设置一个专用按钮,而不是所有复选框,以启动当前选定项上的任务。这不仅更容易实现,而且可能会带来更直观的UI。这是一个很好的建议,这就是我目前正在使用的回退方法。不过我更喜欢Chckbox,因为checked状态提供了关于我选择了什么的信息。有了这个按钮,我必须添加一个标签或一些东西来指示当点击按钮时选择了什么项目。嗨,谢谢你的回复!现在我们接近了。该命令允许我以编程方式设置SelectedItem,但ListBox中有多个项,每个项都有一个复选框模板。如何取消选中其他复选框,保留SelectionMode单一行为?干杯您可以在ViewModel中取消选中这些复选框,更改将反映在UI上,就像您将布尔值列表绑定到选中这些复选框一样,当您要取消选中所有复选框时,只需将列表中的所有值设置为false,并将该列表中的选定项设置为true。这都是关于你在VMTrue中的逻辑做得有多好,这对我来说是一种舒适的方式,因为它类似于表单方式。我的ListBoxItems已经直接绑定到模型业务对象,但我可以创建一个类似ListBoxItemWrapper的包装器,其中T将是BusinessObject。这将需要为一个看起来相当直接的数据绑定场景编写一些代码,但它肯定是一个解决方案。谢谢你好,Nakul,感谢您的回复!至少对于双向绑定来说,这不会改变列表框选择和选中状态。我的目的是让视图模型中的单个属性SelectedItem反映选中列表框中的单个项。干杯
<RadioButton
    Name="rdbSelected"
    GroupName="itemsRadioGroup"
    Command="{Binding 
        RelativeSource={RelativeSource AncestorType=UserControl},
        Path=DataContext.SelectItemCommand}" 
    CommandParameter="{Binding 
        RelativeSource={RelativeSource Self}, 
        Path=DataContext}"/>
RelayCommand<object> cmd = new RelayCommand<object>(
    (o) =>
    {
       if (this.SelectedItem != o)
           this.SelectedItem = o;
    });