例如一个选手机号的程序,有一系列手机号可选。有些手机号已经被人选走了,列表仍然显示它们,但多加一条删除线,如图。
如图,淡色的、被线划掉的就是已经被选走的。这样的功能该如何实现呢?
具体要求
外界可以把这种控件视为ListBox,加元素就是Items.Add,删元素就是Items.Remove。外界不应去关心如何“假删”。
此控件的应用范围应更为广泛,允许用模板来自定义被删除后的显示。
另外,出于个人爱好,此控件内部应尽量简单,少写代码;不重复发明微软专家已经发明的轮子。
实现
- class RetainRemovedListBox : ListBox
- {
- public RetainRemovedListBox()
- {
- ((INotifyCollectionChanged)Items).CollectionChanged += Class1_CollectionChanged;
- }
-
- void Class1_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (e.Action == NotifyCollectionChangedAction.Remove)
- {
- Items.Insert(e.OldStartingIndex, e.OldItems[0]);
- EventHandler itemContainerGeneratorOnStatusChanged = null;
- itemContainerGeneratorOnStatusChanged = (sender1, e1) =>
- {
- if (ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)
- {
- ItemContainerGenerator.StatusChanged -= itemContainerGeneratorOnStatusChanged;
-
- IsRemovedListBoxItem lbi = (IsRemovedListBoxItem)ItemContainerGenerator.ContainerFromItem(e.OldItems[0]);
- lbi.IsRemoved = true;
- lbi.IsEnabled = false;
- }
- };
- ItemContainerGenerator.StatusChanged += itemContainerGeneratorOnStatusChanged;
- }
-
- }
-
- protected override DependencyObject GetContainerForItemOverride()
- {
- return new IsRemovedListBoxItem();
- }
-
- protected override bool IsItemItsOwnContainerOverride(object item)
- {
- return item is IsRemovedListBoxItem;
- }
-
-
- }
-
- class IsRemovedListBoxItem : ListBoxItem
- {
- public static readonly DependencyProperty IsRemovedProperty =
- DependencyProperty.Register("IsRemoved", typeof(bool), typeof(IsRemovedListBoxItem), new FrameworkPropertyMetadata(false));
-
-
- public bool IsRemoved
- {
- get { return (bool)GetValue(IsRemovedProperty); }
- set { SetValue(IsRemovedProperty, value); }
- }
- }
简单解释一下。所谓删除元素,其实删完以后又加了回去,但给它的Container做了记号,于是能够呈现“被删除”的外观。
GetContainerForItemOverride的父类实现是new ListBoxItem。
如果需要真正清除被删除的元素,可以在RetainRemovedListBox里面添加一个方法,对Items里每个元素调用ItemContainerGenerator.ContainerFromItem,检查IsRemoved,然后再删。当然了,Class1_CollectionChanged又会把这个元素添加回去。我相信,勤劳勇敢的中国人能自己解决好这个问题的。
用法
- <Window x:Class="WpfApplication1.MainWindow"
- xmlns=""
- xmlns:x=""
- xmlns:WpfApplication1="clr-namespace:WpfApplication1"
- Title="MainWindow">
- <DockPanel>
- <Button DockPanel.Dock="Top" Content="填充靓号" Padding="10,4" Click="Button_Click" />
- <Button DockPanel.Dock="Bottom" Content="选择" Padding="10,4" Click="Button2_Click" />
- <WpfApplication1:RetainRemovedListBox x:Name="myItemsControl">
- <WpfApplication1:RetainRemovedListBox.ItemTemplate>
- <DataTemplate>
- <TextBlock Name="textBlock" Text="{Binding}"/>
- <DataTemplate.Triggers>
- <DataTrigger Binding="{Binding IsRemoved, RelativeSource={RelativeSource AncestorType=WpfApplication1:IsRemovedListBoxItem}}" Value="True">
- <Setter TargetName="textBlock" Property="TextDecorations" Value="Strikethrough"/>
- DataTrigger>
- DataTemplate.Triggers>
- DataTemplate>
- WpfApplication1:RetainRemovedListBox.ItemTemplate>
- WpfApplication1:RetainRemovedListBox>
- DockPanel>
- Window>
- private void Button2_Click(object sender, RoutedEventArgs e)
- {
- myItemsControl.Items.Remove(myItemsControl.SelectedItem);
- }
填充靓号的代码属技术专利,就不给了。:)
阅读(2803) | 评论(0) | 转发(0) |