selecteditems
前天学习了李永伦老师的贴子,关于使用附加属性让ListBox的SeletedItems属性支持数据绑定.今天再把代码复习一下.
原文本在点击打开链接
在Visual Studio里,我们可以通过propa这个代码段快速创建附加属性。值得提醒的是,你必须同时提供GetSelectedItems和SetSelectedItems两个方法,否则无法在XAML里读或写这个附加属性的值。
这里通过自定义的依赖属性SelectedItems来实现数据绑定,注意SelectedItems只能更新IList这个对象,当我们手动向数据源添加Item时,是不会更新到ListBox的 ,因为
IList这个接口并不像ObseverbleCollection那样实现了INotifyCollectionChanged和INotifyPropertyChanged接口.
自定义这个附加属性的过程中,我觉得最让人难理解的就是下面这个判断
if (e.OldValue != null)
{
listBox.SelectionChanged -= OnlistBoxSelectionChanged;
}
这个判断是用来处理,重复绑定SelectionChanged事件.
要求当数据源发生第二次改变时,取消对SelectionChanged事件的订阅
public class CustomeSelectionItems
{
public static IList GetSelectedItems(DependencyObject obj)
{
return (IList)obj.GetValue(SelectedItemsProperty);
}
public static void SetSelectedItems(DependencyObject obj, IList value)
{
obj.SetValue(SelectedItemsProperty, value);
}
//Using a DependencyProperty as the backing store for SelectedItems. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(CustomeSelectionItems), new PropertyMetadata(OnSelectedItemsChanged));
static public void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var listBox = d as ListBox;
if ((listBox != null) && (listBox.SelectionMode == SelectionMode.Multiple))
{
if (e.OldValue != null)
{
listBox.SelectionChanged -= OnlistBoxSelectionChanged;
}
IList collection = e.NewValue as IList;
listBox.SelectedItems.Clear();
if (collection != null)
{
foreach (var item in collection)
{
listBox.SelectedItems.Add(item);
}
listBox.SelectionChanged += OnlistBoxSelectionChanged;
}
}
}
static void OnlistBoxSelectionChanged(object sender, SelectionChangedEventArgs e)
{
IList dataSource = GetSelectedItems(sender as DependencyObject);
//添加用户选中的当前项.
foreach (var item in e.AddedItems)
{
dataSource.Add(item);
}
//删除用户取消选中的当前项
foreach (var item in e.RemovedItems)
{
dataSource.Remove(item);
}
}
xaml
<ListBox Name="lb" SelectionMode="Multiple"
ItemsSource="{Binding list}"
local:CustomeSelectionItems.SelectedItems="{Binding SelectedItems}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Sex}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
MainPageViewModel
class MainPageViewModel
{
public ObservableCollection<Item> list { get; set; }
public MainPageViewModel()
{
list = new ObservableCollection<Item>();
list.Add(new Item
{
Name = "DDDD",
Sex = "111",
});
list.Add(new Item
{
Name = "DDDD",
Sex = "111",
});
list.Add(new Item
{
Name = "DDDD",
Sex = "111",
});
list.Add(new Item
{
Name = "DDDD",
Sex = "111",
});
list.Add(new Item
{
Name = "DDDD",
Sex = "111",
});
SelectedItems = new ObservableCollection<Item>();
SelectedItems.Add(list[0]);
}
public IList<Item> SelectedItems { get; set; }
}
相关阅读
Tkinter 组件详解之Listbox Listbox(列表框)组件用于显示一个选择列表。Listbox 只能包含文本项目,并且所有的项目都需要使用相同的