欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-16 20:49:30
1、先看下整体效果 2、前端代码 1

1、先看下整体效果

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

 

2、前端代码

重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下
  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、控件后台代码 

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

重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下
  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、数据真实实体

重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下
  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、调用者关心的数据实体(因为绑定数据构建有点麻烦,所以封装了下,使调用者不关心复杂逻辑)

重写TreeView,多层级节点下批量显示图片,图片支持缩略图和文件名列表切换,支持调用者动态匹配选中,支持外界拖入图片并添加到对应节点下
 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类型,标示当前是节点还是节点下的图片显示,如果是节点下的图片,该节点不显示头,显示下面的图片集合

附上关键代码

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

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

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

 

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

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

附上关键代码

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

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

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

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

附上关键代码

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

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

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

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

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

附上关键代码

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

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

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

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

附上关键代码

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

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