using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Data;
using System.Xml;
using System.ComponentModel;
namespace ghostnet_wpf_example
{
///
/// Interaction logic for About.xaml
///
public partial class About : Window
{
///
/// Default constructor is protected so callers must use one with a parent.
///
protected About()
{
InitializeComponent();
}
///
/// Constructor that takes a parent for this About dialog.
///
/// Parent window for this dialog.
public About(Window parent)
: this()
{
this.Owner = parent;
}
///
/// Handles click navigation on the hyperlink in the About dialog.
///
/// Object the sent the event.
/// Navigation events arguments.
private void hyperlink_RequestNavigate(object sender, System.Windows.Navigation.RequestNavigateEventArgs e)
{
if (e.Uri != null && string.IsNullOrEmpty(e.Uri.OriginalString) == false)
{
string uri = e.Uri.AbsoluteUri;
Process.Start(new ProcessStartInfo(uri));
e.Handled = true;
}
}
#region AboutData Provider
#region Member data
private XmlDocument xmlDoc = null;
private const string propertyNameTitle = "Title";
private const string propertyNameDescription = "Description";
private const string propertyNameProduct = "Product";
private const string propertyNameCopyright = "Copyright";
private const string propertyNameCompany = "Company";
private const string xPathRoot = "ApplicationInfo/";
private const string xPathTitle = xPathRoot + propertyNameTitle;
private const string xPathVersion = xPathRoot + "Version";
private const string xPathDescription = xPathRoot + propertyNameDescription;
private const string xPathProduct = xPathRoot + propertyNameProduct;
private const string xPathCopyright = xPathRoot + propertyNameCopyright;
private const string xPathCompany = xPathRoot + propertyNameCompany;
private const string xPathLink = xPathRoot + "Link";
private const string xPathLinkUri = xPathRoot + "Link/@Uri";
#endregion
#region Properties
///
/// Gets the title property, which is display in the About dialogs window title.
///
public string ProductTitle
{
get
{
string result = CalculatePropertyValue(propertyNameTitle, xPathTitle);
if (string.IsNullOrEmpty(result))
{
// otherwise, just get the name of the assembly itself.
result = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
}
return result;
}
}
///
/// Gets the application's version information to show.
///
public string Version
{
get
{
string result = string.Empty;
// first, try to get the version string from the assembly.
Version version = Assembly.GetExecutingAssembly().GetName().Version;
if (version != null)
{
result = version.ToString();
}
else
{
// if that fails, try to get the version from a resource in the Application.
result = GetLogicalResourceString(xPathVersion);
}
return result;
}
}
///
/// Gets the description about the application.
///
public string Description
{
get { return CalculatePropertyValue(propertyNameDescription, xPathDescription);}
}
public string VariableDescription
{
get;
set;
}
///
/// Gets the product's full name.
///
public string Product
{
get { return CalculatePropertyValue(propertyNameProduct, xPathProduct); }
}
///
/// Gets the copyright information for the product.
///
public string Copyright
{
get { return CalculatePropertyValue(propertyNameCopyright, xPathCopyright); }
}
///
/// Gets the product's company name.
///
public string Company
{
get { return CalculatePropertyValue(propertyNameCompany, xPathCompany); }
}
///
/// Gets the link text to display in the About dialog.
///
public string LinkText
{
get { return GetLogicalResourceString(xPathLink); }
}
///
/// Gets the link uri that is the navigation target of the link.
///
public string LinkUri
{
get { return GetLogicalResourceString(xPathLinkUri); }
}
#endregion
#region Resource location methods
///
/// Gets the specified property value either from a specific attribute, or from a resource dictionary.
///
/// Attribute type that we're trying to retrieve.
/// Property name to use on the attribute.
/// XPath to the element in the XML data resource.
/// The resulting string to use for a property.
/// Returns null if no data could be retrieved.
private string CalculatePropertyValue(string propertyName, string xpathQuery)
{
string result = string.Empty;
// first, try to get the property value from an attribute.
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(T), false);
if (attributes.Length > 0)
{
T attrib = (T)attributes[0];
PropertyInfo property = attrib.GetType().GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance);
if (property != null)
{
result = property.GetValue(attributes[0], null) as string;
}
}
// if the attribute wasn't found or it did not have a value, then look in an xml resource.
if (result == string.Empty)
{
// if that fails, try to get it from a resource.
result = GetLogicalResourceString(xpathQuery);
}
return result;
}
///
/// Gets the XmlDataProvider's document from the resource dictionary.
///
protected virtual XmlDocument ResourceXmlDocument
{
get
{
if (xmlDoc == null)
{
// if we haven't already found the resource XmlDocument, then try to find it.
XmlDataProvider provider = this.TryFindResource("aboutProvider") as XmlDataProvider;
if (provider != null)
{
// save away the XmlDocument, so we don't have to get it multiple times.
xmlDoc = provider.Document;
}
}
return xmlDoc;
}
}
///
/// Gets the specified data element from the XmlDataProvider in the resource dictionary.
///
/// An XPath query to the XML element to retrieve.
/// The resulting string value for the specified XML element.
/// Returns empty string if resource element couldn't be found.
protected virtual string GetLogicalResourceString(string xpathQuery)
{
string result = string.Empty;
// get the About xml information from the resources.
XmlDocument doc = this.ResourceXmlDocument;
if (doc != null)
{
// if we found the XmlDocument, then look for the specified data.
XmlNode node = doc.SelectSingleNode(xpathQuery);
if (node != null)
{
if (node is XmlAttribute)
{
// only an XmlAttribute has a Value set.
result = node.Value;
}
else
{
// otherwise, need to just return the inner text.
result = node.InnerText;
}
}
}
return result;
}
#endregion
#endregion
}
}