2009-12-14 34 views
1

我需要使用ItemsSource和CheckedItems属性实现CheckBoxList控件。如果CheckedItems包含这些值,则ItemsSource中的项目应显示为已选中的复选框,否则将取消选中。此外,我需要对CheckedItems属性的双向数据绑定支持(此属性的值应在用户单击复选框时更新)。Silverlight中自定义CheckBoxList控件的CheckedItems属性

这里是一些代码,这可能有助于理解我的问题

XAML:

<UserControl x:Class="Namespace.Controls.CheckBoxList" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <ListBox x:Name="LayoutRoot"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <CheckBox Content="{Binding}"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
</UserControl> 

后面的代码:

public partial class CheckBoxList : UserControl 
{ 
    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CheckBoxList), null); 
    public static readonly DependencyProperty CheckedItemsProperty = DependencyProperty.Register("CheckedItems", typeof(IEnumerable), typeof(CheckBoxList), null); 

    public IEnumerable ItemsSource 
    { 
     get { return (IEnumerable)GetValue(ItemsSourceProperty); } 
     set { SetValue(ItemsSourceProperty, value); } 
    } 
    public IEnumerable CheckedItems 
    { 
     get { return (IEnumerable)GetValue(CheckedItemsProperty); } 
     set { SetValue(CheckedItemsProperty, value); } 
    } 

    public CheckBoxList() 
    { 
     InitializeComponent(); 
     LayoutRoot.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("ItemsSource") { Source = this }); 
    } 
} 

我认为我需要绑定列表框自定义到用户控件转换器,它将返回具有额外的IsChecked属性的项目集合,但它仅适用于单向数据绑定的情况。

看起来我需要同时对两个属性进行双向绑定,但我不知道如何实现它,并且会很感谢这个问题的任何帮助。

在此先感谢。

回答

3

首先,您应该考虑从ListBox而不是UserControl派生。 ListBox已经做了你想要的大部分。其次考虑一种绑定到IList的方式。随后可以在选择相应项目时添加和删除IList的条目。

与其尝试绑定项目模板中的CheckBox控件,您创建ListBox样式的副本,将它们放置在Generic.xaml中作为新控件的样式。然后使用选中和未选中的复选框作为视觉外观的一部分修改未选定和选定的视觉状态。

现在您可以附加到SelectionChanged事件并使用Event args AddedItems列表添加到绑定的IList和RemovedItems列表中,以从绑定列表中删除项目。

当您的CheckedItems被分配或ItemsSource被更改时,您需要清除并重新将项目集添加到列表框SelectedItems列表中。

可能有一些问题需要您解决,但这似乎是一个更直接的路径,而不是从头开始使用UserControl基础。

+0

非常感谢!如果我的想法正确无误(将复选框的状态映射到列表项的选择状态),则可以使用SelectedItems而不是CheckedItems。在这种情况下,我没有看到需要处理SelectionChanged事件。此外,我是Silverlight的新手,因此修改默认的ListBox风格对我来说并不重要:) – altso 2009-12-14 15:01:50

+0

Ooops,SelectedItems不是依赖项属性。需要像你说的那样处理SelectionChanged。 – altso 2009-12-14 15:19:00

+1

是的,你不能指定SelectedItems属性,所以你需要桥接ListBox的SelectedItems属性和你正在公开的新属性,它允许消费者设置一个IList来控制操作。一旦初始SelectedItems设置为分配给您的属性,您可以通过SelectionChanged事件保持两个列表同步。 – AnthonyWJones 2009-12-14 15:30:37

0

您的列表框中的数据源添加可观察集合到您的DataContext:

private ObservableCollection<MyItem> _myItems; 
public ObservableCollection<MyItem> MyItems 
{ 
    get { return _searchByFields; } 
    set 
    { 
     _myItems = value; 
    } 
} 

添加一个类来保存你的复选框中的数据:

public class MyItem 
{ 
    public bool Checked {get; set; } 
    public string MyItemValue { set ; set; } 
} 

然后在你的数据模板绑定列表框收集和您的数据模板复选框到相应的MyItem属性:

<UserControl x:Class="Namespace.Controls.CheckBoxList" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">  
    <ListBox x:Name="LayoutRoot" 
      DataContext="[Dataconext here]" 
      ItemsSource={Binding MyItems}>   
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <CheckBox IsChecked="{Binding Checked, Mode=TwoWay}" 
          Content="{Binding MyItemValue}"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
</UserControl> 

不要忘记将绑定的DataContext设置为适当的类(您可能会在XAML或代码背后执行此操作)

+0

谢谢,但您的解决方案不会在更改复选框状态后更新CheckedItems属性。 – altso 2009-12-14 13:12:50

+0

这假定来自集合的项目有一些“已检查”属性,表明它们已被选中。虽然不清楚这是否会起作用,但它不适用于问题中提出的问题。如果你有一个简单的名单城市为什么应该关心是否是“检查”。那不是问题,由谁来检查,是出于什么原因?如果有多个控件可以从城市中选择,但每个控件都想描述他们自己独特的子集,会怎样? – AnthonyWJones 2009-12-14 13:16:47

+0

要更新属性,请确保绑定是TwoWay – 2009-12-14 13:49:17