2013-07-26 85 views
1

我建立一个WPF应用程序(.NET 4.0),我有以下情况:WPF/MVVM结合复选框selectedItem属性

<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-3s)的异步任务将被启动。 通过简单地选择列表框中的不同项目来排队大量的异步任务是非常容易的,所以我正在研究将ViewModel.SelectedItem绑定到CheckBox(包含在ItemTemplate中)。

我对WPF相当陌生,但在窗体中我会附加一个事件处理程序并编写一些冗长而难看的代码来取消所有项目,但触发事件的项目,然后以编程方式更新属性。我希望有一些更好的解决方案,我已经看过使用ValueConverter,但我不知道如何绑定到父视图模型(具有ObservableCollection <>)。

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

干杯!

./Fredrik

+0

不会吧通过反复点击复选框,排队大量异步任务同样容易吗?我猜你需要的是一种机制,在新的启动时取消当前正在运行的任务。而且您可能会考虑延迟执行任务,而不是在所选项目更改时立即执行。 – Clemens

+0

嗨克莱门斯,thans响应!是的,它会,但是在异步任务运行时防止更改已选状态应该不会太困难。我试图在任务运行时禁用ListBox,但这太难看了。添加CheckBox的好处是ListBox中的选择与任务分离,允许用户在任务运行时浏览列表框。 – Fredrik

+0

您也可以考虑在列表框外部(而不是所有复选框)有一个专用按钮来启动当前选定项目上的任务。这不仅更容易实现,而且还可能导致更直观的用户界面。 – Clemens

回答

0

我想出了一个解决方案,它不会在代码隐藏方面处理已检查的状态,所以我将为后人记录它。

第一个窍门是使用RadioButton代替,并与GroupName相关联。同一组内的单选按钮将自动确保在任何给定时间只检查其中的一个,这可避免手动管理已检查状态的问题。

第二个技巧是将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; 
    }); 
0

嗨可以绑定的复选框司令部VM和该命令将火的时候复选框被选中/取消。

+0

嗨,谢谢你的回应! 现在我们关闭了。该命令让我以编程方式设置SelectedItem,但ListBox中有多个项目,每个项目都使用CheckBox进行模板化。 我将如何取消检查其他CheckBox,保留SelectionMode单行为? 干杯! – Fredrik

+0

您可以在ViewModel中取消选中它们,并且更改将反映在用户界面 – ethicallogics

+0

就像您有布尔绑定到ISelected的那些CheckBoxes列表和当您想取消全部它们然后只设置列表中的所有值false并设置Selected Item列出true。它的一切都关于你在虚拟机中的逻辑有多好 – ethicallogics

0

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

+0

嗨Nakul,感谢您的回应! 实际上这不会改变列表框选择和检查状态(至少对于双向绑定)。我的purpouse是在View-Model中有一个属性SelectedItem反映ListBox中的哪个(单个)项目被选中。 干杯! – Fredrik