博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WPF中,一个文件选择控件的例子
阅读量:5997 次
发布时间:2019-06-20

本文共 5879 字,大约阅读时间需要 19 分钟。

对我来说,WPF比MFC好了不止一百倍:同样的工作,用C#比用C++,开发效率至少提高了200%;在UI制作方面,WPF比MFC更容易做出绚丽的效果;WPF应用程序能嵌入在IE浏览器中,方便部署、维护。随着Windows 7发布脚步的渐进,未来桌面程序的开发,必定属于WPF的。现在,我们还有理由拒绝WPF吗?

接下是一个WPF中文件选择控件的例子,先上效果图:

点击后,出现选择文件对话框:

选择文件后,自动将文件显示在图片框中:

 

代码上很简单,除去VS自动生成的代码,总代码不超过10行,且都是在设计器里用鼠标完成的,整个过程除了输入一些名称,不需要敲一下键盘,历时2分钟:

如果用MFC?估计光按钮上的圆角矩形就需要花半小时吧?

上面代码的核心就是n:FilePicker这个控件了,接下来,我会用一个Step By Step的方式,实现该控件。

新建一个WPF的Custom Control

 

在WPF中,Custom Control和User Control一个最大的不同之处在于,前者需要开发人员编写控件模板,而后者不需要。Custom Control的控件模板包含在项目Themes\Generic.xaml中,点击按钮Add后,Visual Studio向导已为我们自动生成该文件:

设计模板

我们先编译一下,然后在Expression Blend 打开工程,选择编辑Generic.xaml,在边上的Resources面板里,展开Generic.xaml节点,然后双击FilePicker:

可以看到,现在我们的模板仅仅是一个大黑框,其他的什么都没有:

 

现在可以编辑模板了,首先选中Style:

然后在上面选择Edit Template: 

 

添加一个StackPanel、一个Image、一个TextBlock,使模板看起来像这个样子:

把TextBlock命名为tb:

对应的Generix.xaml文件如下:

除了在Generic.xaml里设计模板,我们还需要在静态的构造函数里添加以下代码:

static FilePicker(){    DefaultStyleKeyProperty.OverrideMetadata(typeof(FilePicker),        new FrameworkPropertyMetadata(typeof(FilePicker)));}

添加属性

回到Visual Studio,添加一个辅助类,来表明这个控件选择的文件路径,以及这个文件的图标:

public class FilePickerInfo : INotifyPropertyChanged{    public FilePickerInfo()    {        Icon = IconTools.GetPixel3232Icon("__Folder");    }    public FilePickerInfo(String fullpath)    {        FullPath = fullpath;    }    private String m_FullPath;    public String FullPath    {        get        {            return m_FullPath;        }        set        {            if (value != m_FullPath)            {                m_FullPath = value;                if (PropertyChanged != null)                {                    PropertyChanged(this, new PropertyChangedEventArgs("FullPath"));                }                FileInfo fi = new FileInfo(FullPath);                Icon = IconTools.GetPixel3232Icon(fi.Extension);            }        }    }    private Icon m_Icon;    public Icon Icon    {        get        {            return m_Icon;        }        set        {            if (value != m_Icon)            {                m_Icon = value;                if (PropertyChanged != null)                {                    PropertyChanged(this, new PropertyChangedEventArgs("Icon"));                }            }        }    }    #region INotifyPropertyChanged 成员    public event PropertyChangedEventHandler PropertyChanged;    #endregion}

将FilePickerInfo绑定到模板里

利用WPF的绑定,我要将FilePickerInfo的FullPath属性绑定到模板TextBlock的Text属性上,而把Icon绑定到Image控件的Source属性上。

首先需要在控件中添加两个属性,FSInfo和FullPath。之所以使用依赖属性(DependencyProperty ),是因为DependencyProperty 可以animation、styling、binding等……

public FilePickerInfo FSInfo{    get { return (FilePickerInfo)GetValue(FSInfoProperty); }    set { SetValue(FSInfoProperty, value); }}// Using a DependencyProperty as the backing store for FSInfo.  This enables animation, styling, binding, etc...public static readonly DependencyProperty FSInfoProperty =    DependencyProperty.Register("FSInfo", typeof(FilePickerInfo),    typeof(FilePicker), new UIPropertyMetadata(null));public String FullPath{    get { return (String)GetValue(FullPathProperty); }    set { SetValue(FullPathProperty, value); }}// Using a DependencyProperty as the backing store for FullPath.  This enables animation, styling, binding, etc...public static readonly DependencyProperty FullPathProperty =    DependencyProperty.Register("FullPath", typeof(String), typeof(FilePicker),    new UIPropertyMetadata("请选择文件", new PropertyChangedCallback(OnFullPathChanged)));

 

 

 

 

上述代码最后一行的OnFullPathChanged方法是回调函数,用来执行当FullPath改变时的操作,具体实现见“添加事件”。

编译后,回到Expression Blend,选择模板里的StackPanel,将FSInfo绑定到DataContext上(使用Template Binding):

 

绑定TextBlock的Text属性:

 

绑定Image的Source属性,由于Image控件的Source是ImageSource类型,而我们的图标是System.Drawing.Icon类型的,所以在绑定的过程中需要使用类型转换器:

 

使用的类型转换器代码,将Icon转换成BitmapSource类型:

[ValueConversion(typeof(Icon), typeof(BitmapSource))]public class ImageConverter : IValueConverter{    public object Convert(object value, Type targetType, object parameter,        System.Globalization.CultureInfo culture)    {        if (value == null) return null;        return Imaging.CreateBitmapSourceFromHIcon((value as Icon).Handle, Int32Rect.Empty,            BitmapSizeOptions.FromEmptyOptions());    }    public object ConvertBack(object value, Type targetType, object parameter,        System.Globalization.CultureInfo culture)    {        throw new NotImplementedException();    }}

添加事件

添加一个事件:

/// /// Identifies the ValueChanged routed event./// public static readonly RoutedEvent FullPathChangedEvent = EventManager.RegisterRoutedEvent(    "SelectChanged", RoutingStrategy.Bubble,    typeof(RoutedPropertyChangedEventHandler
), typeof(FilePicker));///
/// Occurs when the Value property changes./// public event RoutedPropertyChangedEventHandler
FullPathChanged{ add { AddHandler(FullPathChangedEvent, value); } remove { RemoveHandler(FullPathChangedEvent, value); }}

 

当控件的FullPath改变时,抛出该事件:

protected static void OnFullPathChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){    FilePicker picker = d as FilePicker;    String oldFullPath = e.OldValue as String;    String fullPath = e.NewValue as String;    picker.FSInfo.FullPath = fullPath;    RoutedPropertyChangedEventArgs
ev = new RoutedPropertyChangedEventArgs
( oldFullPath, fullPath, FullPathChangedEvent); picker.RaiseEvent(ev);}

覆盖OnApplyTemplate函数

修改OnApplyTemplate函数,为模板中的TextBlock添加鼠标单击事件:

public override void OnApplyTemplate(){    base.OnApplyTemplate();    TextBlock tb = this.Template.FindName("tb", this) as TextBlock;    tb.MouseLeftButtonUp += (sender, e) =>    {        FileDialog fd;        fd = new OpenFileDialog();        if (fd.ShowDialog() == true)        {            FullPath = fd.FileName;        }    };}

编译后,该控件就能使用了,只需要把Image控件的Source和该控件的FullPath绑定在一起:

 

下载

转载地址:http://mtwmx.baihongyu.com/

你可能感兴趣的文章
【java堆栈获取后缀表达式】
查看>>
【Swinghacks:JTable单击表头选中列】
查看>>
页面的Tab选项卡 简单实例
查看>>
FTP传输协议的应用详解
查看>>
r语言ggplot2误差棒图快速指南
查看>>
python之处理异常
查看>>
c++中的虚函数
查看>>
遍历form表单里面的表单元素,取其value
查看>>
Socket网络通讯开发总结之:Java 与 C进行Socket通讯(转)
查看>>
逆波兰算法解析计算公式
查看>>
PHP TP框架基础
查看>>
directive ngChecked
查看>>
面试110道题
查看>>
python 08 文件操作
查看>>
uiwebview 清缓存。,mark
查看>>
226. Invert Binary Tree
查看>>
强势解决:windows 不能在本地计算机中起动Tomcat参考特定错误代码1
查看>>
二叉排序树-经典排序
查看>>
折扣显示
查看>>
MySQL SQL语句大全
查看>>