先上图,右边的就是ListView,为什么没用GridView ..因为我还要显示图标形式,暂时没有找GridView如何显示图标形式应该也可以实现。
ListView是继承自ListBox, 其实有时候WPF并不比Winform简单。
图标暂时无视...先随便找的一张图片
关于列头排序,简单的就是在ListView中加入事件 GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler",用tag记录下来当前的顺序,不过列头没有小箭头可以想办法实现。
private void Sort(ListView lv, string sortBy, ListSortDirection direction) { ICollectionView dataView = CollectionViewSource.GetDefaultView(lv.ItemsSource);//获取数据源视图 dataView.SortDescriptions.Clear();//清空默认排序描述 SortDescription sd = new SortDescription(sortBy, direction); dataView.SortDescriptions.Add(sd);//加入新的排序描述 dataView.Refresh();//刷新视图 } private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e) { GridViewColumnHeader gch = e.OriginalSource as GridViewColumnHeader; ListSortDirection direction = ListSortDirection.Descending; if (gch.Tag == null) { gch.Tag = "asc"; } if (gch.Tag.ToString() == "asc") { direction = ListSortDirection.Descending; gch.Tag = "desc"; } else if (gch.Tag.ToString() == "desc") { direction = ListSortDirection.Ascending; gch.Tag = "asc"; } Sort(this.listView1, "Name", direction); }
另外种方法是网上找的自定义附加属性
ListView 显示不同的视图是通过设置其View属性的,它是一个ViewBase,这个类是抽象类需要自己实现。在切换视图的时候需要先将ListView原来的ItemsPanel 记录下来,如果不这样做将图标形式切换到列表信息的时候就会有问题。
切换视图的代码
/// <summary> /// 切换视图 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> void SwitchViewMenu(object sender, RoutedEventArgs args) { MenuItem mi = (MenuItem)sender; if (mi.Header.ToString() == "详细信息") { listView1.View = listView1.FindResource("gridView") as ViewBase; listView1.ItemsPanel = gridItemsPanelTemplate; detailMenu.IsChecked = true; iconMenu.IsChecked = false; } else if (mi.Header.ToString() == "图标") { listView1.View = listView1.FindResource("iconView") as ViewBase; (listView1 as ListBox).ItemTemplate = listView1.FindResource("iconTemplate") as DataTemplate; listView1.ItemsPanel = listView1.FindResource("iconItemsPanelTemplate") as ItemsPanelTemplate; detailMenu.IsChecked = false; iconMenu.IsChecked = true; } }
完整的XAML代码
<Window x:Class="FYJ.Tools.Cloud.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:c="clr-namespace:FYJ.Windows.Controls;assembly=FYJ.Windows.Controls" xmlns:local="clr-namespace:FYJ.Tools.Cloud" xmlns:ext="clr-namespace:FYJ.Windows.Controls.Extention;assembly=FYJ.Windows.Controls" mc:Ignorable="d" Title="云存储工具" Height="350" Width="1000"> <Window.Resources> <GridView x:Key="gridView"> <GridViewColumn Header="名称" Width="300" CellTemplate="{Binding ID}" DisplayMemberBinding="{Binding Name}" ext:ListViewBehavior.SortField="Name"></GridViewColumn> <GridViewColumn Header="修改日期" Width="130" DisplayMemberBinding="{Binding LastModifiedDatetimeString}" ></GridViewColumn> <GridViewColumn Header="大小" Width="100" DisplayMemberBinding="{Binding SizeString}"></GridViewColumn> <GridViewColumn Header="MD5" Width="100" DisplayMemberBinding="{Binding MD5}"></GridViewColumn> <GridViewColumn Header="SHA1" Width="100" DisplayMemberBinding="{Binding SHA1}"></GridViewColumn> </GridView> <local:ImageConvert x:Key="iconConvert"></local:ImageConvert> <DataTemplate x:Key="iconTemplate"> <DockPanel> <Image Width="48" Height="48" DockPanel.Dock="Top" Source="{Binding Path=Icon,Converter={StaticResource iconConvert}}" Margin="2"/> <TextBlock Text="{Binding Name}" FontSize="13" HorizontalAlignment="Center" Margin="0,5,0,0" /> </DockPanel> </DataTemplate> <ItemsPanelTemplate x:Key="iconItemsPanelTemplate"> <!--<VirtualizingStackPanel Orientation="Horizontal"/>--> <WrapPanel Width="{Binding (FrameworkElement.ActualWidth), RelativeSource={RelativeSource AncestorType=ScrollContentPresenter}}" ItemWidth="{Binding (ListView.View).ItemWidth, RelativeSource={RelativeSource AncestorType=ListView}}" ItemHeight="{Binding (ListView.View).ItemHeight,RelativeSource={RelativeSource AncestorType=ListView}}"> </WrapPanel> </ItemsPanelTemplate> <local:PlainView x:Key="iconView" ItemWidth="100" ItemHeight="100" ItemTemplate="{StaticResource iconTemplate}"> </local:PlainView> </Window.Resources> <DockPanel> <StackPanel DockPanel.Dock="Top" Height="40"> <WrapPanel> <Button Content="上传" x:Name="btnUpload" Click="btnUpload_Click"></Button> </WrapPanel> </StackPanel> <StackPanel DockPanel.Dock="Top" Margin="0,5,0,10"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="60"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="40"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="当前路径:" Grid.Column="0"></TextBlock> <TextBox Text="" Margin="5,0,0,0" Grid.Column="1" x:Name="txtCurrentKey"></TextBox> <Button Content="go" Margin="5,0,0,0" Grid.Column="2"></Button> </Grid> </StackPanel> <StackPanel DockPanel.Dock="Bottom"> <StackPanel> <c:LogListBox Margin="0,10,0,10" x:Name="listBox1" DockPanel.Dock="Bottom" Height="80"></c:LogListBox> </StackPanel> <c:TextBlockEx Text="就绪" x:Name="txtStatus"></c:TextBlockEx> </StackPanel> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="250"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <c:CustomTreeView Grid.Column="0" x:Name="objectTree"/> <GridSplitter x:Name="gridSplitter" VerticalAlignment="Stretch" Background="#FF0992F1" Width="1" > </GridSplitter> <ListView Grid.Column="1" x:Name="listView1" ext:ListViewBehavior.HeaderSort="True" GridViewColumnHeader.Click="GridViewColumnHeaderClickedHandler" SelectionChanged="listView1_SelectionChanged"> <ListView.ContextMenu> <ContextMenu> <MenuItem Header="打开"></MenuItem> <MenuItem Header="查看"> <MenuItem Header="详细信息" Click="SwitchViewMenu" IsChecked="True" x:Name="detailMenu"/> <MenuItem Header="图标" Click="SwitchViewMenu" x:Name="iconMenu"/> </MenuItem> <MenuItem Header="排序方式"> <MenuItem Header="名称" Click="SortViewMenu" x:Name="sortNameMenu" /> <MenuItem Header="修改日期" Click="SortViewMenu" x:Name="sortDateMenu" /> <MenuItem Header="大小" Click="SortViewMenu" x:Name="sortSizeMenu"/> </MenuItem> <MenuItem Header="刷新"></MenuItem> <MenuItem Header="上传"></MenuItem> <MenuItem Header="下载"></MenuItem> <MenuItem Header="删除"></MenuItem> <MenuItem Header="上一级"></MenuItem> </ContextMenu> </ListView.ContextMenu> </ListView> </Grid> </DockPanel> </Window>
后台代码
using FYJ.Windows.Controls; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace FYJ.Tools.Cloud { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); objectTree.CheckboxVisibility = Visibility.Collapsed; objectTree.SelectedItemChanged += ObjectTree_SelectedItemChanged; listView1.View = listView1.FindResource("gridView") as ViewBase; } ItemsPanelTemplate gridItemsPanelTemplate; private void ObjectTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e) { TreeModel currentNode = e.NewValue as TreeModel; if (currentNode != null) { List<StoreModel> list = new List<StoreModel>(); foreach (var item in currentNode.Children) { StoreModel model = item.Tag as StoreModel; if (!model.IsDirectory) { model.Icon = "images/cat.png"; } if (model != null) { list.Add(model); } } this.listView1.ItemsSource = list; if (!(this.listView1.View is PlainView)) { gridItemsPanelTemplate = this.listView1.ItemsPanel; } this.txtCurrentKey.Text = currentNode.Id; } } private async void GetChildren2(TreeModel node, IList<TreeModel> list) { string icon = node.Icon; node.Icon = "/FYJ.Windows.Controls;component/Images/16_16/loading.gif"; //await this.Dispatcher.BeginInvoke((Action)(() => //{ txtStatus.Text = "正在加载..."; // })); IStore store = new AliyunStore(); IList<StoreModel> models = new List<StoreModel>(); await Task.Factory.StartNew(() => { StoreModel model = node.Tag as StoreModel; if (model != null) { models = store.ListObject(model.Bucket, model.Key); } }); //await Task.Factory.StartNew(() => //{ // //测试 // Thread.Sleep(1000); //}); foreach (StoreModel model in models) { TreeModel childnode = new TreeModel(); childnode.Id = model.ID; childnode.Name = model.Name; childnode.Icon = model.Icon; childnode.IsExpanded = false; if (model.IsDirectory) { childnode.GetChildren = GetChildren; childnode.Icon = "/FYJ.Windows.Controls;component/Images/16_16/folder.png"; } else { childnode.Icon = "/FYJ.Windows.Controls;component/Images/16_16/file.png"; } childnode.Tag = model; childnode.IsExpanded = false; childnode.IsShowCheckbox = false; list.Add(childnode); } node.Icon = icon; txtStatus.Text = "就绪"; } private IList<TreeModel> GetChildren(TreeModel node) { ObservableCollection<TreeModel> list = new ObservableCollection<TreeModel>(); GetChildren2(node, list); return list; } private async void btnUpload_Click(object sender, RoutedEventArgs e) { txtStatus.Text = "正在加载buckets..."; ObservableCollection<TreeModel> rootTreeList = new ObservableCollection<TreeModel>(); IStore store = new AliyunStore(); IList<string> buckets = store.ListBucket(); await Task.Factory.StartNew(() => { buckets = store.ListBucket(); }); if (buckets.Count == 0) { txtStatus.Text = "就绪"; return; } foreach (string bucket in buckets) { IList<StoreModel> models = new List<StoreModel>(); await Task.Factory.StartNew(() => { models = store.ListObject(bucket, ""); }); foreach (StoreModel model in models) { TreeModel node = new TreeModel(); node.Id = model.ID; node.Name = model.Name; node.IsExpanded = false; if (model.IsDirectory) { node.GetChildren = GetChildren; node.Icon = "/FYJ.Windows.Controls;component/Images/16_16/folder.png"; } else { node.Icon = "/FYJ.Windows.Controls;component/Images/16_16/file.png"; } node.Tag = model; rootTreeList.Add(node); } } this.objectTree.ItemsSourceData = rootTreeList; objectTree.CheckboxVisibility = Visibility.Collapsed; } /// <summary> /// 切换视图 /// </summary> /// <param name="sender"></param> /// <param name="args"></param> void SwitchViewMenu(object sender, RoutedEventArgs args) { MenuItem mi = (MenuItem)sender; if (mi.Header.ToString() == "详细信息") { listView1.View = listView1.FindResource("gridView") as ViewBase; listView1.ItemsPanel = gridItemsPanelTemplate; detailMenu.IsChecked = true; iconMenu.IsChecked = false; } else if (mi.Header.ToString() == "图标") { listView1.View = listView1.FindResource("iconView") as ViewBase; (listView1 as ListBox).ItemTemplate = listView1.FindResource("iconTemplate") as DataTemplate; listView1.ItemsPanel = listView1.FindResource("iconItemsPanelTemplate") as ItemsPanelTemplate; detailMenu.IsChecked = false; iconMenu.IsChecked = true; } } private void Sort(ListView lv, string sortBy, ListSortDirection direction) { ICollectionView dataView = CollectionViewSource.GetDefaultView(lv.ItemsSource);//获取数据源视图 dataView.SortDescriptions.Clear();//清空默认排序描述 SortDescription sd = new SortDescription(sortBy, direction); dataView.SortDescriptions.Add(sd);//加入新的排序描述 dataView.Refresh();//刷新视图 } private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e) { //GridViewColumnHeader gch = e.OriginalSource as GridViewColumnHeader; //ListSortDirection direction = ListSortDirection.Descending; //if (gch.Tag == null) //{ // gch.Tag = "asc"; //} //if (gch.Tag.ToString() == "asc") //{ // direction = ListSortDirection.Descending; // gch.Tag = "desc"; //} //else if (gch.Tag.ToString() == "desc") //{ // direction = ListSortDirection.Ascending; // gch.Tag = "asc"; //} //Sort(this.listView1, "Name", direction); } void SortViewMenu(object sender, RoutedEventArgs args) { MenuItem mi = (MenuItem)sender; ListSortDirection direction = ListSortDirection.Descending; if (mi.Tag == null) { mi.Tag = "asc"; } if (mi.Tag.ToString() == "asc") { direction = ListSortDirection.Descending; mi.Tag = "desc"; } else if (mi.Tag.ToString() == "desc") { direction = ListSortDirection.Ascending; mi.Tag = "asc"; } if (mi.Header.ToString() == "名称") { sortNameMenu.IsChecked = true; sortDateMenu.IsChecked = false; sortSizeMenu.IsChecked = false; Sort(this.listView1, "Name", direction); } else if (mi.Header.ToString() == "修改日期") { sortNameMenu.IsChecked = false; sortDateMenu.IsChecked = true; sortSizeMenu.IsChecked = false; Sort(this.listView1, "LastModifiedDatetimeString", direction); } else if (mi.Header.ToString() == "大小") { sortNameMenu.IsChecked = false; sortDateMenu.IsChecked = false; sortSizeMenu.IsChecked = true; Sort(this.listView1, "Size", direction); } } private void listView1_SelectionChanged(object sender, SelectionChangedEventArgs e) { long size = 0; foreach(var item in this.listView1.SelectedItems) { StoreModel model = item as StoreModel; if(model!=null) { size += model.Size; } } string str = this.listView1.Items.Count+"个项目 选中"+ this.listView1.SelectedItems.Count+" 共"+new SizeConvert().SizeToString(size); this.txtStatus.Text = str; } } }
有一部分是TreeView 的。