1

我正在构建一个 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 绑定到 ViewModel 的 SelectedItem 属性。

但是,当 ViewModel.SelectedItem 更新时,会启动一些长时间运行(2-3 秒)的异步任务。通过简单地选择列表框中的不同项目来排队大量异步任务太容易了,所以我正在研究将 ViewModel.SelectedItem 绑定到 CheckBox(包含在 ItemTemplate 中)。

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

在 WPF 中,我希望有一些更好的解决方案,我已经研究过使用 ValueConverter,但我不知道如何绑定到父 View-Model(具有 ObservableCollection<>)。

如果有人遇到过类似的要求,我真的很感激一些指点。

干杯!

./弗雷德里克

4

3 回答 3

0

嗨,您可以将 CheckBox 绑定到 VM 的命令,当 CheckBox 被选中/取消选中时,该命令将触发。

于 2013-07-26T08:55:18.677 回答
0

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

于 2013-07-26T09:30:25.430 回答
0

我想出了一个不诉诸在代码隐藏中处理检查状态的解决方案,所以我将记录它以供后代使用。

第一个技巧是RadioButton改用 with 和 associated GroupName。同一组中的单选按钮将自动确保在任何给定时间仅选中其中一个,这避免了手动管理选中状态的问题。

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

<RadioButton
    Name="rdbSelected"
    GroupName="itemsRadioGroup"
    Command="{Binding 
        RelativeSource={RelativeSource AncestorType=UserControl},
        Path=DataContext.SelectItemCommand}" 
    CommandParameter="{Binding 
        RelativeSource={RelativeSource Self}, 
        Path=DataContext}"/>

单选按钮命令会在每次单击时触发,不仅仅是在被选中时,但我们可以避免这种情况,因为与CheckBox无法取消选中单选按钮不同,所以双击单选按钮只会确认SelecedItem.

如果该SelectedItem属性触发了一个PropertyChanged事件,建议让命令处理程序检查它是否实际上设置了一个新值,或者只是重复前一个值:

RelayCommand<object> cmd = new RelayCommand<object>(
    (o) =>
    {
       if (this.SelectedItem != o)
           this.SelectedItem = o;
    });
于 2013-08-01T15:55:44.893 回答