最近在做一个WPF的抽奖程序,需要显示人员照片。做的时候把照片全都加到项目里了,作为内容,在ListBox或其他控件中绑定,可以正常显示。但人员照片需要经常添加修改的,总不能每次都重新编译项目吧。因此看了一下WPF中资源文件的引用方式,详见 http://msdn.microsoft.com/zh-cn/library/aa970494.aspx
WPF 应用程序资源、内容和数据文件
根据MSDN的资料:
Microsoft Windows 应用程序通常依赖包含不可执行数据的文件,如Extensible Application Markup Language (XAML)、图像、视频和音频。 Windows Presentation Foundation (WPF) 为配置、识别和使用这些类型的数据文件(称为应用程序数据文件)提供了特殊支持。 这种支持主要针对一组特定的应用程序数据文件类型,包括:
资源文件:编译到可执行或库 WPF 程序集中的数据文件。
内容文件:与可执行 WPF 程序集具有显式关联的独立数据文件。
源站点文件:与可执行 WPF 程序集没有关联的独立数据文件。
这三种类型的文件之间的一个重要区别是:资源文件和内容文件在生成时是已知的;程序集明确地知道它们的存在。 但是对于源站点文件,程序集可能完全不知道它们,或者通过 pack uniform resource identifier (URI) 引用知道它们的存在;在后一种情况下,不能保证被引用的源站点文件实际存在。
目前所需的就是第三种情况,照片并不需要关联到项目里,而是根据实际情况进行更新。因此绑定方式就需要做一下改动了。
简单说一下代码,首先是实体的Person类
public class Person
{
public string Name { get; set; }
public string Photo { get; set; }
}
然后读取指定目录下的照片列表,放到List列表里:(这里最开始的时候是写了一个xml文件,后来一想这不是多此一举么,直接读文件目录不就行了。)
/// <summary>
/// Inits the data.初始化人员数据
/// </summary>
protected void InitData()
{
//以下方法是从xml文件中读取,为了方便,可以直接从目录中读取图片列表
#region 从xml文件中读取
//XmlDocument xdoc = new XmlDocument();
//xdoc.Load("Persons.xml");
//XmlElement root = xdoc.DocumentElement;
//foreach (XmlNode temp in root.ChildNodes)
//{
// Person tempPerson = new Person();
// tempPerson.Name = temp.FirstChild.Value;
// persons.Add(tempPerson);
//}
#endregion
string folderPath = "persons";
System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(folderPath);
FileInfo[] fis = di.GetFiles();
if (fis == null)
{
MessageBox.Show("没有图片!");
App.Current.Shutdown();
}
else
{
foreach (FileInfo fi in fis)
{
Person tempPerson = new Person();
//这里直接获取图片文件名,包括扩展名,方便在图片控件中直接绑定
tempPerson.Name = fi.Name.Substring(0, fi.Name.Length - 4);
tempPerson.Photo = @"persons/" + fi.Name;
persons.Add(tempPerson);
}
}
}
抽奖的时候随机显示人员照片及姓名:
xaml:
<StackPanel Name="pnlRandom" Orientation="Vertical" >
<Image Name="imgPerson" Width="300" Height="400" Source="{Binding Photo,Converter={StaticResource ImgConverter}}" Stretch="UniformToFill" Margin="0,10,0,0"></Image>
<Label x:Name="lblNameShow" HorizontalAlignment="Center" VerticalAlignment="Bottom" FontSize="100" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="#fff45b"/>
</StackPanel>
之前绑定是直接写的 Source="{Binding Photo} ,这样也可以显示,但必须把图片加入到项目里设置成“内容”才能显示出来。现在为了要达到显示没加入到项目里的图片的目的,需要加一个Converter:
[ValueConversion(typeof(string), typeof(string))]
public class ImgConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
//throw new NotImplementedException();
//string strSource = "/LuckyLottery;component/person/" + value + ".jpg";
//return strSource;
BitmapImage img = new BitmapImage();
//若要原始文件的站点,可以调用 Application 类的 GetRemoteStream 方法,同时传递标识原始文件的所需站点的 pack URI。 GetRemoteStream 将返回一个 StreamResourceInfo 对象,该对象将原始文件的该站点作为 Stream 公开,并描述其内容类型。
StreamResourceInfo info = Application.GetRemoteStream(new Uri(value.ToString(), UriKind.Relative));
img.BeginInit();
//img.UriSource = new Uri(value.ToString(), UriKind.Relative);
img.StreamSource = info.Stream;
img.EndInit();
return img;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
需要 using System.Windows.Resources;
这样图片就可以显示出来了。而且可以随意添加删除更新图片。
详细内容可参看MSDN:http://msdn.microsoft.com/zh-cn/library/aa970494.aspx