重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下

1、先看下整体效果

 

2、前端代码

  1 <UserControl x:Class="iPIS.UI.Base.Tree.ImageTreeControl"
  2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
  6              xmlns:local="clr-namespace:iPIS.UI.Base.Tree"
  7              mc:Ignorable="d" 
  8              d:DesignHeight="45" d:DesignWidth="80">
  9     <UserControl.Resources>
 10         <ResourceDictionary>
 11             <ResourceDictionary.MergedDictionaries>
 12                 <ResourceDictionary Source="/iPIS.UI.Themes.Black;component/Base/Tree/VideoTreeControlImages.xaml"/>
 13             </ResourceDictionary.MergedDictionaries>
 14             <Style TargetType="TextBlock" x:Key="treename">
 15                 <Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlFontColor}"></Setter>
 16                 <Setter Property="FontSize" Value="14"></Setter>
 17             </Style>
 18         </ResourceDictionary>
 19     </UserControl.Resources>
 20     <TreeView x:Name="tree" 
 21               ItemsSource="{Binding DataList}"
 22               Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlBackground}"
 23               >
 24         <TreeView.ItemTemplate>
 25             <HierarchicalDataTemplate ItemsSource="{Binding Children}">
 26                 <Grid Margin="-1 0 0 0"
 27                       Cursor="Hand"
 28                       Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlBackground}"
 29                       >
 30                     <StackPanel x:Name="Classify" Orientation="Horizontal">
 31                         <Image Source="{Binding IconSource}" 
 32                                Width="25" 
 33                                Height="25" 
 34                                VerticalAlignment="Center"
 35                                Margin="0 0 10 0"
 36                                ></Image>
 37                         <TextBlock Text="{Binding Text}" 
 38                                    VerticalAlignment="Center"
 39                                    Style="{StaticResource treename}">
 40                         </TextBlock>
 41                         <TextBlock Style="{StaticResource treename}"
 42                                    VerticalAlignment="Center"
 43                             ></TextBlock>
 44                         <TextBlock Text="{Binding ImagesCount}"
 45                                    VerticalAlignment="Center"
 46                                    Style="{StaticResource treename}"
 47                                    ></TextBlock>
 48                         <TextBlock Style="{StaticResource treename}"
 49                                    VerticalAlignment="Center"
 50                             ></TextBlock>
 51                     </StackPanel>
 52                     <!--缩略图视图-->
 53                     <ListBox x:Name="Image_slt" 
 54                              ItemsSource="{Binding Images}" 
 55                              Visibility="Collapsed"
 56                              Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ThumbnailWidth}"
 57                              Background="Transparent"
 58                              Margin="-35 0 0 0"
 59                              >
 60                         <ListBox.Template>
 61                             <ControlTemplate TargetType="{x:Type ListBox}">
 62                                 <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
 63                                     <WrapPanel Orientation="Horizontal" IsItemsHost="True"></WrapPanel>
 64                                 </ScrollViewer>
 65                             </ControlTemplate>
 66                         </ListBox.Template>
 67                         <ListBox.ItemTemplate>
 68                             <DataTemplate>
 69                                 <Border x:Name="border" 
 70                                         BorderBrush="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageBoderColor}" 
 71                                         Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageBoderColor}"
 72                                         BorderThickness="3"                            
 73                                         Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageWidth}" 
 74                                         Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageHeight}"
 75                                         >
 76                                     <Grid>
 77                                         <Image Source="{Binding ImageSource}"
 78                                                Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageWidth}" 
 79                                                Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageHeight}" 
 80                                                ></Image>
 81                                         <Image x:Name="icon" Visibility="Collapsed" Width="13" Height="14" Margin="-72 -50 0 0"></Image>
 82                                     </Grid>
 83                                 </Border>
 84                                 <DataTemplate.Triggers>
 85                                     <DataTrigger Binding="{Binding Type}" Value="1">
 86                                         <Setter TargetName="icon" Property="Visibility" Value="Visible"></Setter>
 87                                         <Setter TargetName="icon" Property="Source" Value="{StaticResource icon_kou}"></Setter>
 88                                     </DataTrigger>
 89                                     <DataTrigger Binding="{Binding Type}" Value="2">
 90                                         <Setter TargetName="icon" Property="Visibility" Value="Visible"></Setter>
 91                                         <Setter TargetName="icon" Property="Source" Value="{StaticResource icon_jiandao}"></Setter>
 92                                     </DataTrigger>
 93                                     <DataTrigger Binding="{Binding IsSelected}" Value="true">
 94                                         <Setter TargetName="border" 
 95                                                 Property="BorderBrush" 
 96                                                 Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageSelectedBoderColor}"
 97                                                 ></Setter>
 98                                     </DataTrigger>
 99                                     <Trigger Property="IsMouseOver" Value="true">
100                                         <Setter TargetName="border" 
101                                                 Property="BorderBrush" 
102                                                 Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageMouseOverBoderColor}"
103                                                 ></Setter>
104                                     </Trigger>
105                                 </DataTemplate.Triggers>
106                             </DataTemplate>
107                         </ListBox.ItemTemplate>
108                         <ListBox.ItemContainerStyle>
109                             <Style TargetType="ListBoxItem">
110                                 <Setter Property="Padding" Value="0"></Setter>
111                                 <Setter Property="BorderThickness" Value="0"></Setter>
112                                 <Setter Property="Margin" Value="1"></Setter>
113                             </Style>
114                         </ListBox.ItemContainerStyle>
115                     </ListBox>
116                     <!--文件名视图-->
117                     <ListBox x:Name="Image_file" 
118                              ItemsSource="{Binding Images}"
119                              BorderThickness="0"
120                              Background="Transparent"
121                              Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ListWidth}"
122                              Margin="-35 0 0 0"
123                              >
124                         <ListBox.ItemTemplate>
125                             <DataTemplate>
126                                 <TextBlock x:Name="text" 
127                                            Text="{Binding Text}"
128                                            Foreground="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageImgNameColor}"
129                                            ></TextBlock>
130                                 <DataTemplate.Triggers>
131                                     <DataTrigger Binding="{Binding IsSelected}" Value="true">
132                                         <Setter TargetName="text" 
133                                                 Property="Foreground" 
134                                                 Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlImageSelectedImgNameColor}"
135                                                 ></Setter>
136                                     </DataTrigger>
137                                 </DataTemplate.Triggers>
138                             </DataTemplate>
139                         </ListBox.ItemTemplate>
140                     </ListBox>
141                 </Grid>
142                 <HierarchicalDataTemplate.Triggers>
143                     <DataTrigger Binding="{Binding Type}" Value="0">
144                         <Setter TargetName="Classify" Property="Visibility" Value="Visible"></Setter>
145                         <Setter TargetName="Image_slt" Property="Visibility" Value="Collapsed"></Setter>
146                         <Setter TargetName="Image_file" Property="Visibility" Value="Collapsed"></Setter>
147                     </DataTrigger>
148                     <DataTrigger Binding="{Binding Type}" Value="1">
149                         <Setter TargetName="Classify" Property="Visibility" Value="Collapsed"></Setter>
150                     </DataTrigger>
151                     <MultiDataTrigger>
152                         <MultiDataTrigger.Conditions>
153                             <Condition Binding="{Binding Type}" Value="1"></Condition>
154                             <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlViewState}" Value="0"></Condition>
155                         </MultiDataTrigger.Conditions>
156                         <Setter TargetName="Image_slt" Property="Visibility" Value="Collapsed"></Setter>
157                         <Setter TargetName="Image_file" Property="Visibility" Value="Visible"></Setter>
158                     </MultiDataTrigger>
159                     <MultiDataTrigger>
160                         <MultiDataTrigger.Conditions>
161                             <Condition Binding="{Binding Type}" Value="1"></Condition>
162                             <Condition Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=local:ImageTreeControl},Path=ImageTreeControlViewState}" Value="1"></Condition>
163                         </MultiDataTrigger.Conditions>
164                         <Setter TargetName="Image_slt" Property="Visibility" Value="Visible"></Setter>
165                         <Setter TargetName="Image_file" Property="Visibility" Value="Collapsed"></Setter>
166                     </MultiDataTrigger>
167                 </HierarchicalDataTemplate.Triggers>
168 
169             </HierarchicalDataTemplate>
170         </TreeView.ItemTemplate>
171     </TreeView>
172 </UserControl>
View Code

 

3、控件后台代码 

  1 using iPIS.UI.Base.Model;
  2 using iPIS.UI.Base.ViewModel;
  3 using iPIS.Utility;
  4 using System;
  5 using System.Collections.Generic;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Threading.Tasks;
  9 using System.Windows;
 10 using System.Windows.Controls;
 11 using System.Windows.Data;
 12 using System.Windows.Documents;
 13 using System.Windows.Input;
 14 using System.Windows.Media;
 15 using System.Windows.Media.Imaging;
 16 using System.Windows.Navigation;
 17 using System.Windows.Shapes;
 18 
 19 namespace iPIS.UI.Base.Tree
 20 {
 21     /// <summary>
 22     /// ImageTreeControl.xaml 的交互逻辑
 23     /// </summary>
 24     public partial class ImageTreeControl : UserControl
 25     {
 26         public ImageTreeControl()
 27         {
 28             InitializeComponent();
 29             var vm = new ImageTreeControlViewModel(this);
 30             this.DataContext = vm;
 31             this.PreviewDragOver += ImageTreeControl_PreviewDragOver;
 32             this.PreviewDrop += ImageTreeControl_PreviewDrop;
 33             this.SizeChanged += ImageTreeControl_SizeChanged;
 34 
 35             //默认样式
 36             ImageTreeControlViewState = 1;
 37             ImageTreeControlImageWidth = 85;
 38             ImageTreeControlImageHeight = 65;
 39             ImageTreeControlBackground = "#36353a";
 40             ImageTreeControlFontColor = "#89888d";
 41             ImageTreeControlImageBoderColor = "#000000";
 42             ImageTreeControlImageSelectedBoderColor = "#019e97";
 43             ImageTreeControlImageMouseOverBoderColor = ImageTreeControlImageSelectedBoderColor;
 44             ImageTreeControlImageImgNameColor = ImageTreeControlFontColor;
 45             ImageTreeControlImageSelectedImgNameColor = ImageTreeControlImageSelectedBoderColor;
 46 
 47             //测试数据
 48             test();
 49         }
 50 
 51         /// <summary>
 52         /// 大小发送变化时
 53         /// </summary>
 54         /// <param name="sender"></param>
 55         /// <param name="e"></param>
 56         private void ImageTreeControl_SizeChanged(object sender, SizeChangedEventArgs e)
 57         {
 58             ThumbnailWidth = (int)this.Width - 10;
 59             ListWidth = (int)this.Width - 25;
 60         }
 61 
 62         private void test()
 63         {
 64             //模拟数据
 65             var list = new Client.WebApiWrap.PVL.FileCategoryApiWrap().GetFileCategoryList("ac165316-6630-40ba-84bb-fba75475d713", 2, 2, -1, 1);
 66             var datas = new List<ImageTreeControlItemModel>();
 67             for (int j = 0; j < list.Count; j++)
 68             {
 69                 var item = list[j];
 70                 ImageTreeControlItemModel root = new ImageTreeControlItemModel();
 71                 root.Text = item.CategoryName;
 72                 root.Value = item;
 73                 root.Images = new List<ImageTreeControlImageModel>();
 74                 for (int i = 0; i < 10; i++)
 75                 {
 76                     root.Images.Add(new ImageTreeControlImageModel()
 77                     {
 78                         ImageSource = new BitmapImage(new Uri(PublicMethod.GetSet("Web") + "/images/defaut.png")),
 79                         Text = "我是名称"
 80                     });
 81                 }
 82                 if (j == list.Count - 1)
 83                 {
 84                     ImageTreeControlItemModel m = new ImageTreeControlItemModel();
 85                     m.Text = "我是第二级";
 86                     m.Images = new List<ImageTreeControlImageModel>();
 87                     for (int i = 0; i < 10; i++)
 88                     {
 89                         m.Images.Add(new ImageTreeControlImageModel()
 90                         {
 91                             ImageSource = new BitmapImage(new Uri(PublicMethod.GetSet("Web") + "/images/defaut.png")),
 92                             Text = "我是第二级的图片"
 93                         });
 94                     }
 95                     root.Children = new List<ImageTreeControlItemModel>() { m };
 96                 }
 97                 datas.Add(root);
 98             }
 99             vm.SetDataList(datas);
100         }
101 
102         /// <summary>
103         /// 上下文
104         /// </summary>
105         public ImageTreeControlViewModel vm
106         {
107             get
108             {
109                 return this.DataContext as ImageTreeControlViewModel;
110             }
111         }
112 
113         /// <summary>
114         /// 背景色
115         /// </summary>
116         public string ImageTreeControlBackground
117         {
118             get { return (string)GetValue(ImageTreeControlBackgroundProperty); }
119             set { SetValue(ImageTreeControlBackgroundProperty, value); }
120         }
121 
122         /// <summary>
123         /// 视图状态,默认文件名形式
124         /// 0:文件名称;1:缩略图
125         /// </summary>
126         public int ImageTreeControlViewState
127         {
128             get { return (int)GetValue(ImageTreeControlViewStateProperty); }
129             set { SetValue(ImageTreeControlViewStateProperty, value); }
130         }
131 
132         /// <summary>
133         /// 缩略图模式,显示的图片宽度
134         /// </summary>
135         public int ImageTreeControlImageWidth
136         {
137             get { return (int)GetValue(ImageTreeControlImageWidthProperty); }
138             set { SetValue(ImageTreeControlImageWidthProperty, value); }
139         }
140 
141         /// <summary>
142         /// 缩略图模式,显示的图片高度
143         /// </summary>
144         public int ImageTreeControlImageHeight
145         {
146             get { return (int)GetValue(ImageTreeControlImageHeightProperty); }
147             set { SetValue(ImageTreeControlImageHeightProperty, value); }
148         }
149 
150         /// <summary>
151         /// 树状控件的节点名称字体样式
152         /// </summary>
153         public string ImageTreeControlFontColor
154         {
155             get { return (string)GetValue(ImageTreeControlFontColorProperty); }
156             set { SetValue(ImageTreeControlFontColorProperty, value); }
157         }
158 
159         /// <summary>
160         /// 默认状态下,图片的边框样式
161         /// </summary>
162         public string ImageTreeControlImageBoderColor
163         {
164             get { return (string)GetValue(ImageTreeControlImageBoderColorProperty); }
165             set { SetValue(ImageTreeControlImageBoderColorProperty, value); }
166         }
167 
168         /// <summary>
169         /// 缩略图模式的容器宽度
170         /// </summary>
171         public int ThumbnailWidth
172         {
173             get { return (int)GetValue(ThumbnailWidthProperty); }
174             private set { SetValue(ThumbnailWidthProperty, value); }
175         }
176 
177         /// <summary>
178         /// 文件名称视图的容器宽度
179         /// </summary>
180         public int ListWidth
181         {
182             get { return (int)GetValue(ListWidthProperty); }
183             private set { SetValue(ListWidthProperty, value); }
184         }
185 
186         /// <summary>
187         /// 选中状态下,图片边框的样式
188         /// </summary>
189         public string ImageTreeControlImageSelectedBoderColor
190         {
191             get { return (string)GetValue(ImageTreeControlImageSelectedBoderColorProperty); }
192             set { SetValue(ImageTreeControlImageSelectedBoderColorProperty, value); }
193         }
194 
195         /// <summary>
196         /// 鼠标悬浮图片上,图片边框的样式
197         /// </summary>
198         public string ImageTreeControlImageMouseOverBoderColor
199         {
200             get { return (string)GetValue(ImageTreeControlImageMouseOverBoderColorProperty); }
201             set { SetValue(ImageTreeControlImageMouseOverBoderColorProperty, value); }
202         }
203 
204         /// <summary>
205         /// 默认状态,列表模式,图片名称的样式
206         /// </summary>
207         public string ImageTreeControlImageImgNameColor
208         {
209             get { return (string)GetValue(ImageTreeControlImageImgNameColorProperty); }
210             set { SetValue(ImageTreeControlImageImgNameColorProperty, value); }
211         }
212 
213         /// <summary>
214         /// 选中状态下,列表模式,图片名称的样式
215         /// </summary>
216         public string ImageTreeControlImageSelectedImgNameColor
217         {
218             get { return (string)GetValue(ImageTreeControlImageSelectedImgNameColorProperty); }
219             set { SetValue(ImageTreeControlImageSelectedImgNameColorProperty, value); }
220         }
221 
222         #region 附加属性
223 
224         public static readonly DependencyProperty ListWidthProperty =
225             DependencyProperty.Register("ListWidth", typeof(int), typeof(ImageTreeControl), new PropertyMetadata(0));
226 
227         public static readonly DependencyProperty ThumbnailWidthProperty =
228             DependencyProperty.Register("ThumbnailWidth", typeof(int), typeof(ImageTreeControl), new PropertyMetadata(0));
229 
230         public static readonly DependencyProperty ImageTreeControlImageMouseOverBoderColorProperty =
231             DependencyProperty.Register("ImageTreeControlImageMouseOverBoderColor", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
232 
233         public static readonly DependencyProperty ImageTreeControlImageImgNameColorProperty =
234             DependencyProperty.Register("ImageTreeControlImageImgNameColor", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
235 
236         public static readonly DependencyProperty ImageTreeControlImageSelectedImgNameColorProperty =
237             DependencyProperty.Register("ImageTreeControlImageSelectedImgNameColor", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
238 
239         public static readonly DependencyProperty ImageTreeControlImageSelectedBoderColorProperty =
240             DependencyProperty.Register("ImageTreeControlImageSelectedBoderColor", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
241 
242         public static readonly DependencyProperty ImageTreeControlImageBoderColorProperty =
243             DependencyProperty.Register("ImageTreeControlImageBoderColor", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
244 
245         public static readonly DependencyProperty ImageTreeControlFontColorProperty =
246             DependencyProperty.Register("ImageTreeControlFontColor", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
247 
248         public static readonly DependencyProperty ImageTreeControlImageHeightProperty =
249             DependencyProperty.Register("ImageTreeControlImageHeight", typeof(int), typeof(ImageTreeControl), new PropertyMetadata(0));
250 
251         public static readonly DependencyProperty ImageTreeControlImageWidthProperty =
252             DependencyProperty.Register("ImageTreeControlImageWidth", typeof(int), typeof(ImageTreeControl), new PropertyMetadata(0));
253 
254         public static readonly DependencyProperty ImageTreeControlViewStateProperty =
255             DependencyProperty.Register("ImageTreeControlViewState", typeof(int), typeof(ImageTreeControl), new PropertyMetadata(0));
256 
257         public static readonly DependencyProperty ImageTreeControlBackgroundProperty =
258             DependencyProperty.Register("ImageTreeControlBackground", typeof(string), typeof(ImageTreeControl), new PropertyMetadata(""));
259 
260         #endregion
261 
262         /// <summary>
263         /// 拖进来了
264         /// </summary>
265         /// <param name="sender"></param>
266         /// <param name="e"></param>
267         private void ImageTreeControl_PreviewDrop(object sender, DragEventArgs e)
268         {
269             var data = e.Data.GetData(typeof(ImageTreeControlImageModel));
270             if (data == null) return;
271             Point point = e.GetPosition(tree);
272             HitTestResult result = VisualTreeHelper.HitTest(tree, point);
273             if (result == null)
274                 return;
275             TreeViewItem treeitem = Utils.FindVisualParent<TreeViewItem>(result.VisualHit);
276             if (treeitem == null)
277                 return;
278             var vm_item = treeitem.DataContext as ImageTreeControlItemModelPackage;
279             if (vm_item == null)
280                 return;
281             if (vm_item.Type == ImageTreeControlItemType.Classify)
282             {
283                 var imags = vm_item.Children.Where(c => c.Type == ImageTreeControlItemType.Images).ToList();
284                 if (imags.Count == 0)
285                 {
286                     ImageTreeControlItemModelPackage item = new ImageTreeControlItemModelPackage(vm_item);
287                     item.Type = ImageTreeControlItemType.Images;
288                     vm_item.Children.Add(item);
289                     imags = vm_item.Children.Where(c => c.Type == ImageTreeControlItemType.Images).ToList();
290                 }
291                 else if (imags.Count > 1)
292                 {
293                     MessageBox.Show("抱歉,当前节点下面有多个子集,无法确定你想存放的位置,请拖到对应节点下!");
294                     return;
295                 }
296                 var imgItem = imags.FirstOrDefault();
297                 imgItem.Images.Insert(0, data as ImageTreeControlImageModel);
298                 imgItem.Parent.NotifyToImagesCount();//图片集合发生变动,发出通知
299             }
300             else if (vm_item.Type == ImageTreeControlItemType.Images)
301             {
302                 vm_item.Images.Insert(0, data as ImageTreeControlImageModel);
303                 vm_item.Parent.NotifyToImagesCount();//图片集合发生变动,发出通知
304             }
305         }
306 
307         /// <summary>
308         /// 当有数据拖动进来时
309         /// </summary>
310         /// <param name="sender"></param>
311         /// <param name="e"></param>
312         private void ImageTreeControl_PreviewDragOver(object sender, DragEventArgs e)
313         {
314             e.Effects = DragDropEffects.Copy;
315             e.Handled = e.Data.GetData(typeof(ImageTreeControlImageModel)) != null;
316         }
317     }
318 
319     internal static class Utils
320     {
321         public static T FindVisualParent<T>(DependencyObject obj) where T : class
322         {
323             while (obj != null)
324             {
325                 if (obj is T)
326                     return obj as T;
327 
328                 obj = VisualTreeHelper.GetParent(obj);
329             }
330 
331             return null;
332         }
333     }
334 }
View Code

 

4、控件datacontext对象

  1 using iPIS.Server.Core;
  2 using iPIS.UI.Base.Model;
  3 using iPIS.UI.Base.Tree;
  4 using iPIS.Utility;
  5 using System;
  6 using System.Collections.Generic;
  7 using System.Collections.ObjectModel;
  8 using System.ComponentModel;
  9 using System.Linq;
 10 using System.Text;
 11 using System.Threading.Tasks;
 12 
 13 namespace iPIS.UI.Base.ViewModel
 14 {
 15     public class ImageTreeControlViewModel : System.ComponentModel.INotifyPropertyChanged
 16     {
 17         public event PropertyChangedEventHandler PropertyChanged;
 18         private ImageTreeControl imageTreeControl;
 19 
 20         public ImageTreeControlViewModel(ImageTreeControl imageTreeControl)
 21         {
 22             this.imageTreeControl = imageTreeControl;
 23         }
 24 
 25         private ObservableCollection<ImageTreeControlItemModelPackage> _DataList = new ObservableCollection<ImageTreeControlItemModelPackage>();
 26 
 27         /// <summary>
 28         /// 数据集合,请使用 函数SetDataList,进行赋值构建
 29         /// </summary>
 30         public ObservableCollection<ImageTreeControlItemModelPackage> DataList
 31         {
 32             get => _DataList;
 33             private set
 34             {
 35                 _DataList = value;
 36                 PropertyChanged?.Notify(() => this.DataList);
 37             }
 38         }
 39 
 40         /// <summary>
 41         /// 视图状态,默认文件名形式
 42         /// 0:文件名称;1:缩略图
 43         /// </summary>
 44         public int ViewState
 45         {
 46             get => imageTreeControl.ImageTreeControlViewState;
 47             set
 48             {
 49                 imageTreeControl.ImageTreeControlViewState = value;
 50             }
 51         }
 52 
 53         /// <summary>
 54         /// 发出数据变更通知通知
 55         /// </summary>
 56         /// <param name="vm"></param>
 57         public void NotifyToDataList()
 58         {
 59             PropertyChanged?.Notify(() => this.DataList);
 60         }
 61 
 62         /// <summary>
 63         /// 选中匹配成功的 text
 64         /// </summary>
 65         /// <param name="text">需要匹配的名称</param>
 66         /// <param name="isfullvalue">true:全值匹配;false:模糊匹配</param>
 67         /// <returns></returns>
 68         public List<object> SelectedItem(string text, bool isfullvalue)
 69         {
 70             if (string.IsNullOrEmpty(text)) return new List<object>(); ;
 71             List<object> outlist = new List<object>();
 72             SetSelected(DataList, text, isfullvalue, outlist);
 73             if (outlist.Count > 0)
 74                 PropertyChanged?.Notify(() => this.DataList);
 75             return outlist;
 76         }
 77 
 78         /// <summary>
 79         /// 选中匹配成功的 id
 80         /// </summary>
 81         /// <param name="Id"></param>
 82         /// <returns></returns>
 83         public object SelectedItem(string Id)
 84         {
 85             if (string.IsNullOrEmpty(Id)) return new { };
 86             object outob = null;
 87             SetSelected(DataList, Id, ref outob);
 88             if (outob != null)
 89                 PropertyChanged?.Notify(() => this.DataList);
 90             return outob;
 91         }
 92 
 93         /// <summary>
 94         /// 获取所有的图片
 95         /// </summary>
 96         /// <param name="imageType">图片类型,默认返回所有类型</param>
 97         /// <returns></returns>
 98         public List<ImageTreeControlImageModel> GetAllImages(ImageTreeControlImageType imageType = ImageTreeControlImageType.None)
 99         {
100             List<ImageTreeControlImageModel> list = new List<ImageTreeControlImageModel>();
101             return list;
102         }
103 
104         /// <summary>
105         /// 设置选中状态
106         /// </summary>
107         /// <param name="items"></param>
108         /// <param name="text"></param>
109         /// <param name="isfullvalue"></param>
110         /// <param name="selecteditems"></param>
111         private void SetSelected(ObservableCollection<ImageTreeControlItemModelPackage> items, string text, bool isfullvalue, List<object> selecteditems = null)
112         {
113             if (selecteditems == null) selecteditems = new List<object>();
114 
115             foreach (var item in items)
116             {
117                 if (item.Type == ImageTreeControlItemType.Classify)
118                 {
119                     item.IsSelected = isfullvalue && item.Text.Equals(text) || !isfullvalue && item.Text.Contains(text);
120                     if (item.IsSelected)
121                         selecteditems.Add(item);
122                 }
123                 else
124                 {
125                     foreach (var img in item.Images)
126                     {
127                         img.IsSelected = isfullvalue && img.Text.Equals(text) || !isfullvalue && img.Text.Contains(text);
128                         if (img.IsSelected)
129                             selecteditems.Add(img);
130                     }
131                 }
132                 SetSelected(item.Children, text, isfullvalue, selecteditems);
133             }
134         }
135 
136         /// <summary>
137         /// 设置选中状态
138         /// </summary>
139         /// <param name="items"></param>
140         /// <param name="id"></param>
141         /// <param name="selecteditem"></param>
142         private void SetSelected(ObservableCollection<ImageTreeControlItemModelPackage> items, string id, ref object selecteditem)
143         {
144             foreach (var item in items)
145             {
146                 if (item.Type == ImageTreeControlItemType.Classify)
147                 {
148                     item.IsSelected = item.Id.Equals(id);
149                     if (item.IsSelected)
150                         selecteditem = item;
151                 }
152                 else
153                 {
154                     foreach (var img in item.Images)
155                     {
156                         img.IsSelected = img.Id.Equals(id);
157                         if (img.IsSelected)
158                             selecteditem = img;
159                     }
160                 }
161                 SetSelected(item.Children, id, ref selecteditem);
162             }
163         }
164 
165         /// <summary>
166         /// 设置数据源
167         /// </summary>
168         /// <param name="items"></param>
169         public void SetDataList(List<ImageTreeControlItemModel> items)
170         {
171             DataList.Clear();
172             ObservableCollection<ImageTreeControlItemModelPackage> roots = new ObservableCollection<ImageTreeControlItemModelPackage>();
173             foreach (var item in items)
174             {
175                 ImageTreeControlItemModelPackage itemP = new ImageTreeControlItemModelPackage(null);
176                 itemP.Type = ImageTreeControlItemType.Classify;
177                 itemP.Id = item.Id;
178                 itemP.Text = item.Text;
179                 itemP.Value = item.Value;
180                 //递归设置子集
181                 SetChildren(item.Children, itemP);
182                 //处理图片
183                 SetImages(item, itemP);
184                 //设置图标
185                 itemP.IconSource = item.IconSource;
186                 //系统内置的root图标给予覆盖
187                 SetRootIcon(itemP);
188                 roots.Add(itemP);
189             }
190             DataList = roots;
191         }
192 
193         /// <summary>
194         /// 递归设置子集
195         /// </summary>
196         /// <param name="items"></param>
197         /// <param name="parent"></param>
198         private void SetChildren(List<ImageTreeControlItemModel> items, ImageTreeControlItemModelPackage parent)
199         {
200             if (items == null || items.Count == 0) return;
201 
202             foreach (var item in items)
203             {
204                 ImageTreeControlItemModelPackage itemP = new ImageTreeControlItemModelPackage(parent);
205                 itemP.Id = item.Id;
206                 itemP.Text = item.Text;
207                 itemP.Value = item.Value;
208                 //递归设置子集
209                 SetChildren(item.Children, itemP);
210                 //处理图片
211                 SetImages(item, itemP);
212                 parent.Children.Add(itemP);
213             }
214         }
215 
216         /// <summary>
217         /// 设置当前实体的图片集合
218         /// </summary>
219         /// <param name="item"></param>
220         /// <param name="parent"></param>
221         private void SetImages(ImageTreeControlItemModel item, ImageTreeControlItemModelPackage parent)
222         {
223             if (item.Images == null || item.Images.Count == 0) return;
224 
225             ImageTreeControlItemModelPackage imgP = new ImageTreeControlItemModelPackage(parent);
226             imgP.Type = ImageTreeControlItemType.Images;
227             foreach (var img in item.Images)
228             {
229                 imgP.Images.Add(img);
230             }
231             parent.Children.Add(imgP);
232         }
233 
234         /// <summary>
235         /// 设置根节点的图标
236         /// </summary>
237         private void SetRootIcon(ImageTreeControlItemModelPackage root)
238         {
239             if (root.Parent != null) return;
240             var fc = root.Value as filecategory;
241             if (fc == null) return;
242             if (fc.CategorySource != 1) return;
243             var url = string.Empty;
244             switch (fc.CategoryName)
245             {
246                 case "头部五官":
247                     url = PublicMethod.GetSet("Web") + "/Images/ImageCategoryIcons/人像鉴定系统-文书icons正面.png";
248                     break;
249                 case "人体动态":
250                     url = PublicMethod.GetSet("Web") + "/Images/ImageCategoryIcons/人像鉴定系统-文书icons人体动态.png";
251                     break;
252                 case "身高":
253                     url = PublicMethod.GetSet("Web") + "/Images/ImageCategoryIcons/人像鉴定系统-文书icons身高.png";
254                     break;
255                 case "特殊标示":
256                     url = PublicMethod.GetSet("Web") + "/Images/ImageCategoryIcons/人像鉴定系统-文书icons特殊.png";
257                     break;
258                 case "衣着配饰":
259                     url = PublicMethod.GetSet("Web") + "/Images/ImageCategoryIcons/人像鉴定系统-文书icons衣服.png";
260                     break;
261                 case "其他":
262                     break; ;
263                 default:
264                     break;
265             }
266             if (!string.IsNullOrEmpty(url))
267                 root.IconSource = new System.Windows.Media.Imaging.BitmapImage(new Uri(url, UriKind.Absolute));
268         }
269     }
270 }
View Code

 

5、数据真实实体

  1 using iPIS.UI.Base.ViewModel;
  2 using System;
  3 using System.Collections.Generic;
  4 using System.Collections.ObjectModel;
  5 using System.ComponentModel;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Threading.Tasks;
  9 using System.Windows.Media.Imaging;
 10 
 11 namespace iPIS.UI.Base.Model
 12 {
 13     /// <summary>
 14     /// 图片树状,子项实体的包装类,请使用 ImageTreeControlItemModel 完成构建
 15     /// </summary>
 16     public class ImageTreeControlItemModelPackage : INotifyPropertyChanged
 17     {
 18 
 19         public event PropertyChangedEventHandler PropertyChanged;
 20         private string _Id = string.Empty;
 21         private bool _IsSelected = false;
 22 
 23         /// <summary>
 24         /// 当前的父级
 25         /// </summary>
 26         /// <param name="Parent">当前元素的父级,null代表无父级,顶层元素</param>
 27         public ImageTreeControlItemModelPackage(ImageTreeControlItemModelPackage Parent)
 28         {
 29             this.Parent = Parent;
 30         }
 31 
 32         /// <summary>
 33         /// 唯一标示
 34         /// </summary>
 35         public string Id
 36         {
 37             get
 38             {
 39                 if (string.IsNullOrEmpty(_Id)) _Id = Guid.NewGuid().ToString();
 40                 return _Id;
 41             }
 42             set => _Id = value;
 43         }
 44 
 45         /// <summary>
 46         /// 当前类型
 47         /// </summary>
 48         public ImageTreeControlItemType Type { get; set; } = ImageTreeControlItemType.Classify;
 49 
 50         /// <summary>
 51         /// 分类名称,type=Classify 时有效
 52         /// </summary>
 53         public string Text { get; set; }
 54 
 55         /// <summary>
 56         /// 绑定值
 57         /// </summary>
 58         public object Value { get; set; }
 59 
 60         /// <summary>
 61         /// 分类图标,type=Classify 时有效
 62         /// </summary>
 63         public BitmapImage IconSource { get; set; } = null;
 64 
 65         /// <summary>
 66         /// 所属的集合,type=Classify 时有效
 67         /// </summary>
 68         public ObservableCollection<ImageTreeControlItemModelPackage> Children { get; set; } = new ObservableCollection<ImageTreeControlItemModelPackage>();
 69 
 70         /// <summary>
 71         /// 当前的父级
 72         /// </summary>
 73         public ImageTreeControlItemModelPackage Parent { get; set; }
 74 
 75         /// <summary>
 76         /// 所属的图片集合,type=Images 时有效
 77         /// UI已经构建的模块,新增插入编辑集合,请使用帮助函数
 78         /// </summary>
 79         public ObservableCollection<ImageTreeControlImageModel> Images { get; set; } = new ObservableCollection<ImageTreeControlImageModel>();
 80 
 81         /// <summary>
 82         /// 当前下的图片集合,type=Classify 时有效
 83         /// </summary>
 84         public ObservableCollection<ImageTreeControlImageModel> GetImages
 85         {
 86             get
 87             {
 88                 if (Type == ImageTreeControlItemType.Images)
 89                     return new ObservableCollection<ImageTreeControlImageModel>();
 90                 ObservableCollection<ImageTreeControlImageModel> list = new ObservableCollection<ImageTreeControlImageModel>();
 91                 foreach (var item in Children.Where(c => c.Type == ImageTreeControlItemType.Images))
 92                 {
 93                     foreach (var img in item.Images)
 94                     {
 95                         list.Add(img);
 96                     }
 97                 }
 98                 return list;
 99             }
100         }
101 
102         /// <summary>
103         /// 是否选中
104         /// </summary>
105         public bool IsSelected
106         {
107             get
108             {
109                 return _IsSelected;
110             }
111             set
112             {
113                 _IsSelected = value;
114                 PropertyChanged?.Notify(() => this.IsSelected);
115             }
116         }
117 
118         /// <summary>
119         /// 当前下的图片集合数量,type=Classify 时有效
120         /// </summary>
121         public int ImagesCount
122         {
123             get => GetImages.Count;
124         }
125 
126         /// <summary>
127         /// 当前下的图片集合数量,type=Classify 时有效
128         /// </summary>
129         public void NotifyToImagesCount()
130         {
131             if (Type == ImageTreeControlItemType.Classify)
132                 PropertyChanged?.Notify(() => this.ImagesCount);
133         }
134     }
135 
136     /// <summary>
137     /// 图片树状,所属子项的图片实体
138     /// </summary>
139     public class ImageTreeControlImageModel : INotifyPropertyChanged
140     {
141         public event PropertyChangedEventHandler PropertyChanged;
142         private string _Id = string.Empty;
143         private bool _IsSelected = false;
144         private ImageTreeControlImageType _Type = ImageTreeControlImageType.Default;
145 
146         /// <summary>
147         /// 唯一标示
148         /// </summary>
149         public string Id
150         {
151             get
152             {
153                 if (string.IsNullOrEmpty(_Id)) _Id = Guid.NewGuid().ToString();
154                 return _Id;
155             }
156             set => _Id = value;
157         }
158 
159         /// <summary>
160         /// 图片名称
161         /// </summary>
162         public string Text { get; set; }
163 
164         /// <summary>
165         /// 绑定值
166         /// </summary>
167         public object Value { get; set; }
168 
169         /// <summary>
170         /// 图片资源
171         /// </summary>
172         public BitmapImage ImageSource { get; set; } = null;
173 
174         /// <summary>
175         /// 图片类型
176         /// </summary>
177         public ImageTreeControlImageType Type
178         {
179             get
180             {
181                 return _Type;
182             }
183             set
184             {
185                 _Type = value;
186                 PropertyChanged?.Notify(() => this.Type);
187             }
188         }
189 
190         /// <summary>
191         /// 是否选中
192         /// </summary>
193         public bool IsSelected
194         {
195             get
196             {
197                 return _IsSelected;
198             }
199             set
200             {
201                 _IsSelected = value;
202                 PropertyChanged?.Notify(() => this.IsSelected);
203             }
204         }
205     }
206 
207     /// <summary>
208     /// 图片树状,子项类型
209     /// </summary>
210     public enum ImageTreeControlItemType
211     {
212         /// <summary>
213         /// 分类
214         /// </summary>
215         Classify = 0,
216         /// <summary>
217         /// 图片资源
218         /// </summary>
219         Images = 1
220     }
221 
222     /// <summary>
223     /// 图片树状,所属子项的图片的类型
224     /// </summary>
225     public enum ImageTreeControlImageType
226     {
227         /// <summary>
228         /// 什么也不是
229         /// </summary>
230         None = -1,
231         /// <summary>
232         /// 默认
233         /// </summary>
234         Default = 0,
235         /// <summary>
236         /// 抠图
237         /// </summary>
238         Matting = 1,
239         /// <summary>
240         /// 已经对此抠图了
241         /// </summary>
242         AlreadyMatting = 2
243     }
244 }
View Code

 

6、调用者关心的数据实体(因为绑定数据构建有点麻烦,所以封装了下,使调用者不关心复杂逻辑)

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Windows.Media.Imaging;
 7 
 8 namespace iPIS.UI.Base.Model
 9 {
10     /// <summary>
11     /// 图片树状,子项实体
12     /// </summary>
13     public class ImageTreeControlItemModel
14     {
15         /// <summary>
16         /// 唯一标示符
17         /// </summary>
18         public string Id { get; set; }
19 
20         /// <summary>
21         /// 显示名称
22         /// </summary>
23         public string Text { get; set; }
24 
25         /// <summary>
26         /// 绑定值
27         /// </summary>
28         public object Value { get; set; }
29 
30         /// <summary>
31         /// 当前的下级
32         /// </summary>
33         public List<ImageTreeControlItemModel> Children { get; set; }
34 
35         /// <summary>
36         /// 当前节点下的图片集合
37         /// </summary>
38         public List<ImageTreeControlImageModel> Images { get; set; }
39 
40         /// <summary>
41         /// 类别显示图标
42         /// </summary>
43         public BitmapImage IconSource { get; set; } = null;
44     }
45 }
View Code

 

好了,该控件的全部代码已经看完了,下面我就把我遇到的问题进行按个阐述,且附上解决方案

1、首要问题就是如何才能节点下面再批量显示图片

答:通过假节点来实现,每个节点绑定一个Type类型,标示当前是节点还是节点下的图片显示,如果是节点下的图片,该节点不显示头,显示下面的图片集合

附上关键代码

 

2、如何缩略图和文件列表的动图切换

答:起初考虑这个属性设置在datacontext还是控件里,最开始是想放在datacontext里的,但是,UI上的绑定出了问题,找了几圈没得合适的解决办法,迫于无奈就放在控件里了,通过附加属性控制,细心的朋友应该会发现是利用的多条件的触发器,因为需要首先满足当前节点是图片集合的容器,详情可参照问题1

附上关键代码

3、调用者需要动态的设置选中

答:通过数据实体继承INotifyPropertyChanged接口,实现通知即可实现;特别说明,因为在vm里面只能对数据集发起变更的通知,所以数据源发送的变动需要自助发起通知,子集会自动更新的,至于原理我也不是很清楚,反正不通知就没戏,亲测

附上关键代码

4、因为实现了拖住,允许接收外界的数据,需要动态载入节点中,如何更新UI和更新父级节点的统计数量

答:实现原理和问题3差不多,需要提醒的是,由于集合发生变动,需要发起通知才行,否则是不会更新的,请看关键代码

附上关键代码

 5、由于数据结果过于复杂,调用是无需关心的,所以需要给调用者提供简易的数据构建函数

答:数据源的赋值访问设置为私有,杜绝外部写入,通过公开函数构建

附上关键代码

 

posted @ 2018-07-18 11:46  吃奶嘴的路飞  阅读(899)  评论(0编辑  收藏  举报