Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43739
  • 博文数量: 7
  • 博客积分: 270
  • 博客等级: 入伍新兵
  • 技术积分: 130
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-04 09:29
文章分类
文章存档

2012年(7)

分类: 嵌入式

2012-07-29 11:43:41

例如一个选手机号的程序,有一系列手机号可选。有些手机号已经被人选走了,列表仍然显示它们,但多加一条删除线,如图。

如图,淡色的、被线划掉的就是已经被选走的。这样的功能该如何实现呢?


具体要求

外界可以把这种控件视为ListBox,加元素就是Items.Add,删元素就是Items.Remove。外界不应去关心如何“假删”。

此控件的应用范围应更为广泛,允许用模板来自定义被删除后的显示。

另外,出于个人爱好,此控件内部应尽量简单,少写代码;不重复发明微软专家已经发明的轮子。

实现

[csharp] view plaincopy
  1. class RetainRemovedListBox : ListBox  
  2.    {  
  3.        public RetainRemovedListBox()  
  4.        {  
  5.            ((INotifyCollectionChanged)Items).CollectionChanged += Class1_CollectionChanged;  
  6.        }  
  7.   
  8.        void Class1_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)  
  9.        {  
  10.            if (e.Action == NotifyCollectionChangedAction.Remove)  
  11.            {  
  12.                Items.Insert(e.OldStartingIndex, e.OldItems[0]);  
  13.                EventHandler itemContainerGeneratorOnStatusChanged = null;  
  14.                itemContainerGeneratorOnStatusChanged = (sender1, e1) =>  
  15.                        {  
  16.                            if (ItemContainerGenerator.Status == System.Windows.Controls.Primitives.GeneratorStatus.ContainersGenerated)  
  17.                            {  
  18.                                ItemContainerGenerator.StatusChanged -= itemContainerGeneratorOnStatusChanged;  
  19.   
  20.                                IsRemovedListBoxItem lbi = (IsRemovedListBoxItem)ItemContainerGenerator.ContainerFromItem(e.OldItems[0]);  
  21.                                lbi.IsRemoved = true;  
  22.                                lbi.IsEnabled = false;  
  23.                            }  
  24.                        };  
  25.                ItemContainerGenerator.StatusChanged += itemContainerGeneratorOnStatusChanged;  
  26.            }  
  27.   
  28.        }  
  29.   
  30.        protected override DependencyObject GetContainerForItemOverride()  
  31.        {  
  32.            return new IsRemovedListBoxItem();  
  33.        }  
  34.   
  35.        protected override bool IsItemItsOwnContainerOverride(object item)  
  36.        {  
  37.            return item is IsRemovedListBoxItem;  
  38.        }  
  39.   
  40.   
  41.    }  
  42.   
  43.    class IsRemovedListBoxItem : ListBoxItem  
  44.    {  
  45.        public static readonly DependencyProperty IsRemovedProperty =   
  46.            DependencyProperty.Register("IsRemoved"typeof(bool), typeof(IsRemovedListBoxItem), new FrameworkPropertyMetadata(false));  
  47.   
  48.   
  49.        public bool IsRemoved  
  50.        {  
  51.            get { return (bool)GetValue(IsRemovedProperty); }  
  52.            set { SetValue(IsRemovedProperty, value); }  
  53.        }  
  54.    }  

简单解释一下。所谓删除元素,其实删完以后又加了回去,但给它的Container做了记号,于是能够呈现“被删除”的外观。

GetContainerForItemOverride的父类实现是new ListBoxItem。

如果需要真正清除被删除的元素,可以在RetainRemovedListBox里面添加一个方法,对Items里每个元素调用ItemContainerGenerator.ContainerFromItem,检查IsRemoved,然后再删。当然了,Class1_CollectionChanged又会把这个元素添加回去。我相信,勤劳勇敢的中国人能自己解决好这个问题的。

用法


  1. <Window x:Class="WpfApplication1.MainWindow"  
  2.         xmlns=""  
  3.         xmlns:x=""   
  4.         xmlns:WpfApplication1="clr-namespace:WpfApplication1"  
  5.         Title="MainWindow">  
  6.     <DockPanel>  
  7.         <Button DockPanel.Dock="Top" Content="填充靓号" Padding="10,4" Click="Button_Click" />  
  8.         <Button DockPanel.Dock="Bottom" Content="选择"  Padding="10,4" Click="Button2_Click" />  
  9.         <WpfApplication1:RetainRemovedListBox x:Name="myItemsControl">  
  10.             <WpfApplication1:RetainRemovedListBox.ItemTemplate>  
  11.                 <DataTemplate>  
  12.                     <TextBlock Name="textBlock" Text="{Binding}"/>  
  13.                     <DataTemplate.Triggers>  
  14.                         <DataTrigger Binding="{Binding IsRemoved, RelativeSource={RelativeSource AncestorType=WpfApplication1:IsRemovedListBoxItem}}" Value="True">  
  15.                             <Setter TargetName="textBlock" Property="TextDecorations" Value="Strikethrough"/>  
  16.                         DataTrigger>  
  17.                     DataTemplate.Triggers>  
  18.                 DataTemplate>  
  19.             WpfApplication1:RetainRemovedListBox.ItemTemplate>  
  20.         WpfApplication1:RetainRemovedListBox>  
  21.     DockPanel>  
  22. Window>  

[csharp] view plaincopy
  1. private void Button2_Click(object sender, RoutedEventArgs e)  
  2. {  
  3.     myItemsControl.Items.Remove(myItemsControl.SelectedItem);  
  4. }  

填充靓号的代码属技术专利,就不给了。:)


阅读(2803) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~