2009-12-14 35 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