اگر به برنامههاي جديد نوشته شده براي ويندوز 7 دقت كنيم، از يك سري امكانات مخصوص آن جهت بهبود دسترسي پذيري به قابليتهايي كه ارائه ميدهند، استفاده شده است. براي مثال برنامهي OneNote مجموعهي آفيس را در نظر بگيريد. اگر بر روي آيكون آن در نوار وظيفهي ويندوز كليك راست كنيم، ليست آخرين فايلهاي گشوده شده توسط آن مشخص است و با كليك بر روي هر كدام، به سادگي ميتوان اين فايل را گشود. يك چنين قابليتي در منوي آغازين ويندوز نيز تعبيه شده است (شكلهاي زير):
خبر خوب اينكه براي اضافه كردن اين قابليت به برنامههاي WPF4 نيازي به كد نويسي نيست و اين موارد كه تحت عنوان استفاده از Jump list ويندوز 7 تعريف شدهاند، با كمي دستكاري فايل App.Xaml برنامه، فعال ميگردند:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
<JumpList.JumpList>
<JumpList ShowRecentCategory="True" />
</JumpList.JumpList>
</Application>
سؤال: من اينكار را انجام دادم ولي كار نميكنه!؟
پاسخ: بله. كار نميكنه! اين قابليت تنها زماني فعال خواهد شد كه علاوه بر نكتهي فوق، پسوند فايل يا فايلهايي نيز به برنامهي شما منتسب شده باشد. اين انتسابها مطلب جديدي نيست و در تمام برنامههاي ويندوزي بايد توسط بكارگيري API ويندوز مديريت شود. قطعه كد زير اينكار را انجام خواهد داد:
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Common.Files
{
//from : http://www.devx.com/vb2themax/Tip/19554?type=kbArticle&trk=MSCP
public class FileAssociation
{
const int ShcneAssocchanged = 0x8000000;
const int ShcnfIdlist = 0;
public static void CreateFileAssociation(
string extension,
string className,
string description,
string exeProgram)
{
// ensure that there is a leading dot
if (extension.Substring(0, 1) != ".")
extension = string.Format(".{0}", extension);
try
{
if (IsAssociated(extension)) return;
// create a value for this key that contains the classname
using (var key1 = Registry.ClassesRoot.CreateSubKey(extension))
{
if (key1 != null)
{
key1.SetValue("", className);
// create a new key for the Class name
using (var key2 = Registry.ClassesRoot.CreateSubKey(className))
{
if (key2 != null)
{
key2.SetValue("", description);
// associate the program to open the files with this extension
using (var key3 = Registry.ClassesRoot.CreateSubKey(string.Format(@"{0}\Shell\Open\Command", className)))
{
if (key3 != null) key3.SetValue("", string.Format(@"{0} ""%1""", exeProgram));
}
}
}
}
}
// notify Windows that file associations have changed
SHChangeNotify(ShcneAssocchanged, ShcnfIdlist, 0, 0);
}
catch (Exception ex)
{
//todo: log ...
}
}
// Return true if extension already associated in registry
public static bool IsAssociated(string extension)
{
return (Registry.ClassesRoot.OpenSubKey(extension, false) != null);
}
[DllImport("shell32.dll")]
public static extern void SHChangeNotify(int wEventId, int uFlags, int dwItem1, int dwItem2);
}
}
private static void createFileAssociation()
{
var appPath = Assembly.GetExecutingAssembly().Location;
FileAssociation.CreateFileAssociation(".xyz", "xyz", "xyz File",
appPath
);
}
سؤال: من اين كارها را هم انجام دادم. الان به چه صورت از آن استفاده كنم؟
زمانيكه كاربري بر روي يكي از اين فايلهاي ذكر شده در ليست آخرين فايلهاي گشوده شده توسط برنامه كليك كند، آدرس اين فايل به صورت يك آرگومان به برنامه ارسال خواهد شد. براي مديريت آن در WPF بايد به فايل App.Xaml.cs مراجعه كرده و چند سطر زير را به آن افزود:
public partial class App
{
public App()
{
this.Startup += appStartup;
}
void appStartup(object sender, StartupEventArgs e)
{
if (e.Args.Any())
{
this.Properties["StartupFileName"] = e.Args[0];
}
}
//...
در اين كد، e.Args حاوي مسير فايل انتخابي است. براي مثال در اينجا مقدار آن به خاصيت StartupFileName انتساب داده شده است. اين خاصيت در برنامههاي WPF به صورت يك خاصيت عمومي تعريف شده است و در سراسر برنامه (مثلا در رخداد آغاز فرم اصلي آن يا هر جاي ديگري) به صورت زير قابل دسترسي است:
var startupFileName = Application.Current.Properties["StartupFileName"];
سؤال: برنامهي من از OpenFileDialog براي گشودن فايلها استفاده نميكند. آيا راه ديگري براي افزودن مسيرهاي باز شده به Jump lists ويندوز 7 وجود دارد؟
پاسخ: بله. همانطور كه ميدانيد عناصر XAML با اشياء دات نت تناظر يك به يك دارند. به اين معنا كه JumpList تعريف شده در ابتداي اين مطلب در فايل App.XAML ، دقيقا معادل كلاسي به همين نام در دات نت فريم ورك است (تعريف شده در فضاي نام System.Windows.Shell) و با كد نويسي نيز قابل دسترسي و مديريت است. براي مثال:
var jumpList = JumpList.GetJumpList(App.Current);
var jumpPath = new JumpPath();
jumpPath.Path = "some path goes here....";
// If the CustomCategory property is null
// or Empty, the item is added to the Tasks category
jumpPath.CustomCategory = "Files";
JumpList.AddToRecentCategory(jumpPath);
jumpList.Apply();
<Application x:Class="Win7Wpf4.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
<JumpList.JumpList>
<JumpList ShowRecentCategory="True">
<JumpPath
CustomCategory="Files"
Path="Some path goes here..."
/>
</JumpList>
</JumpList.JumpList>
</Application>