先上图,右边的就是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 的。
珂珂的个人博客 - 一个程序猿的个人网站