Minor code improvements

This commit is contained in:
ClemensF 2012-07-07 17:19:10 +02:00
parent 6b25260536
commit 472658a6d9
19 changed files with 301 additions and 175 deletions

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.Caching; using System.Runtime.Caching;
@ -18,25 +19,61 @@ namespace Caching
private const string expiresField = "Expires"; private const string expiresField = "Expires";
private readonly BinaryFormatter formatter = new BinaryFormatter(); private readonly BinaryFormatter formatter = new BinaryFormatter();
private readonly FileDb fileDb = new FileDb(); private readonly FileDb fileDb = new FileDb { AutoFlush = false, AutoCleanThreshold = -1 };
private readonly string name; private readonly string name;
private readonly string path; private readonly string path;
public FileDbCache(string name, string path) public FileDbCache(string name, NameValueCollection config)
: this(name, config["directory"])
{ {
if (string.IsNullOrEmpty(path)) string autoFlush = config["autoFlush"];
string autoCleanThreshold = config["autoCleanThreshold"];
if (autoFlush != null)
{ {
throw new ArgumentException("The parameter path must not be null or empty."); try
{
fileDb.AutoFlush = bool.Parse(autoFlush);
}
catch (Exception ex)
{
throw new ArgumentException("The configuration parameter autoFlush must be a boolean value.", ex);
}
} }
if (autoCleanThreshold != null)
{
try
{
fileDb.AutoCleanThreshold = int.Parse(autoCleanThreshold);
}
catch (Exception ex)
{
throw new ArgumentException("The configuration parameter autoCleanThreshold must be an integer value.", ex);
}
}
}
public FileDbCache(string name, string directory)
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentException("The parameter name must not be null or empty.");
}
if (string.IsNullOrEmpty(directory))
{
throw new ArgumentException("The parameter directory must not be null or empty.");
}
this.name = name;
path = Path.Combine(directory, name);
if (string.IsNullOrEmpty(Path.GetExtension(path))) if (string.IsNullOrEmpty(Path.GetExtension(path)))
{ {
path += ".fdb"; path += ".fdb";
} }
this.name = name;
this.path = path;
try try
{ {
fileDb.Open(path, false); fileDb.Open(path, false);
@ -46,7 +83,7 @@ namespace Caching
CreateDatebase(); CreateDatebase();
} }
Trace.TraceInformation("FileDbCache created with {0} cached items", fileDb.NumRecords); Trace.TraceInformation("FileDbCache: Opened database with {0} cached items in {1}", fileDb.NumRecords, path);
} }
public bool AutoFlush public bool AutoFlush
@ -96,21 +133,24 @@ namespace Caching
long count = 0; long count = 0;
try if (fileDb.IsOpen)
{ {
count = fileDb.NumRecords; try
}
catch
{
if (CheckReindex())
{ {
count = fileDb.NumRecords;
}
catch (Exception ex1)
{
Trace.TraceWarning("FileDbCache: FileDb.NumRecords failed: {0}", ex1.Message);
try try
{ {
fileDb.Reindex();
count = fileDb.NumRecords; count = fileDb.NumRecords;
} }
catch catch (Exception ex2)
{ {
CreateDatebase(); Trace.TraceWarning("FileDbCache: FileDb.Reindex() failed: {0}", ex2.Message);
} }
} }
} }
@ -118,75 +158,64 @@ namespace Caching
return count; return count;
} }
public override bool Contains(string key, string regionName = null) private Record GetRecord(string key)
{ {
if (regionName != null) Record record = null;
if (fileDb.IsOpen)
{ {
throw new NotSupportedException("The parameter regionName must be null."); try
{
record = fileDb.GetRecordByKey(key, new string[] { valueField }, false);
}
catch (Exception ex1)
{
Trace.TraceWarning("FileDbCache: FileDb.GetRecordByKey(\"{0}\") failed: {1}", key, ex1.Message);
try
{
fileDb.Reindex();
record = fileDb.GetRecordByKey(key, new string[] { valueField }, false);
}
catch (Exception ex2)
{
Trace.TraceWarning("FileDbCache: FileDb.Reindex() failed: {0}", ex2.Message);
}
}
} }
return record;
}
public override bool Contains(string key, string regionName = null)
{
if (key == null) if (key == null)
{ {
throw new ArgumentNullException("The parameter key must not be null."); throw new ArgumentNullException("The parameter key must not be null.");
} }
bool contains = false; if (regionName != null)
try
{ {
contains = fileDb.GetRecordByKey(key, new string[0], false) != null; throw new NotSupportedException("The parameter regionName must be null.");
}
catch
{
if (CheckReindex())
{
try
{
contains = fileDb.GetRecordByKey(key, new string[0], false) != null;
}
catch
{
CreateDatebase();
}
}
} }
return contains; return GetRecord(key) != null;
} }
public override object Get(string key, string regionName = null) public override object Get(string key, string regionName = null)
{ {
if (regionName != null)
{
throw new NotSupportedException("The parameter regionName must be null.");
}
if (key == null) if (key == null)
{ {
throw new ArgumentNullException("The parameter key must not be null."); throw new ArgumentNullException("The parameter key must not be null.");
} }
object value = null; if (regionName != null)
Record record = null; {
throw new NotSupportedException("The parameter regionName must be null.");
}
try object value = null;
{ Record record = GetRecord(key);
record = fileDb.GetRecordByKey(key, new string[] { valueField }, false);
}
catch
{
if (CheckReindex())
{
try
{
record = fileDb.GetRecordByKey(key, new string[] { valueField }, false);
}
catch
{
CreateDatebase();
}
}
}
if (record != null) if (record != null)
{ {
@ -197,16 +226,17 @@ namespace Caching
value = formatter.Deserialize(stream); value = formatter.Deserialize(stream);
} }
} }
catch (Exception exc) catch (Exception ex1)
{ {
Trace.TraceWarning("FileDbCache.Get({0}): {1}", key, exc.Message); Trace.TraceWarning("FileDbCache: Failed deserializing item \"{0}\": {1}", key, ex1.Message);
try try
{ {
fileDb.DeleteRecordByKey(key); fileDb.DeleteRecordByKey(key);
} }
catch catch (Exception ex2)
{ {
Trace.TraceWarning("FileDbCache: FileDb.DeleteRecordByKey(\"{0}\") failed: {1}", key, ex2.Message);
} }
} }
} }
@ -239,9 +269,9 @@ namespace Caching
public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null) public override void Set(string key, object value, CacheItemPolicy policy, string regionName = null)
{ {
if (regionName != null) if (key == null)
{ {
throw new NotSupportedException("The parameter regionName must be null."); throw new ArgumentNullException("The parameter key must not be null.");
} }
if (value == null) if (value == null)
@ -249,53 +279,57 @@ namespace Caching
throw new ArgumentNullException("The parameter value must not be null."); throw new ArgumentNullException("The parameter value must not be null.");
} }
if (key == null) if (regionName != null)
{ {
throw new ArgumentNullException("The parameter key must not be null."); throw new NotSupportedException("The parameter regionName must be null.");
} }
byte[] valueBuffer = null; if (fileDb.IsOpen)
try
{ {
using (MemoryStream stream = new MemoryStream()) byte[] valueBuffer = null;
{
formatter.Serialize(stream, value);
valueBuffer = stream.ToArray();
}
}
catch (Exception exc)
{
Trace.TraceWarning("FileDbCache.Set({0}): {1}", key, exc.Message);
}
if (valueBuffer != null)
{
DateTime expires = DateTime.MaxValue;
if (policy.AbsoluteExpiration != InfiniteAbsoluteExpiration)
{
expires = policy.AbsoluteExpiration.DateTime;
}
else if (policy.SlidingExpiration != NoSlidingExpiration)
{
expires = DateTime.UtcNow + policy.SlidingExpiration;
}
try try
{ {
AddOrUpdateRecord(key, valueBuffer, expires); using (MemoryStream stream = new MemoryStream())
}
catch
{
if (CheckReindex())
{ {
formatter.Serialize(stream, value);
valueBuffer = stream.ToArray();
}
}
catch (Exception ex)
{
Trace.TraceWarning("FileDbCache: Failed serializing item \"{0}\": {1}", key, ex.Message);
}
if (valueBuffer != null)
{
DateTime expires = DateTime.MaxValue;
if (policy.AbsoluteExpiration != InfiniteAbsoluteExpiration)
{
expires = policy.AbsoluteExpiration.DateTime;
}
else if (policy.SlidingExpiration != NoSlidingExpiration)
{
expires = DateTime.UtcNow + policy.SlidingExpiration;
}
try
{
AddOrUpdateRecord(key, valueBuffer, expires);
}
catch (Exception ex1)
{
Trace.TraceWarning("FileDbCache: FileDb.UpdateRecordByKey(\"{0}\") failed: {1}", key, ex1.Message);
try try
{ {
fileDb.Reindex();
AddOrUpdateRecord(key, valueBuffer, expires); AddOrUpdateRecord(key, valueBuffer, expires);
} }
catch catch (Exception ex2)
{ {
Trace.TraceWarning("FileDbCache: FileDb.Reindex() failed: {0}, creating new database", ex2.Message);
CreateDatebase(); CreateDatebase();
AddOrUpdateRecord(key, valueBuffer, expires); AddOrUpdateRecord(key, valueBuffer, expires);
} }
@ -343,8 +377,9 @@ namespace Caching
{ {
fileDb.DeleteRecordByKey(key); fileDb.DeleteRecordByKey(key);
} }
catch catch (Exception ex)
{ {
Trace.TraceWarning("FileDbCache: FileDb.DeleteRecordByKey(\"{0}\") failed: {1}", key, ex.Message);
} }
} }
@ -357,9 +392,9 @@ namespace Caching
{ {
fileDb.Flush(); fileDb.Flush();
} }
catch catch (Exception ex)
{ {
CheckReindex(); Trace.TraceWarning("FileDbCache: FileDb.Flush() failed: {0}", ex.Message);
} }
} }
@ -369,40 +404,29 @@ namespace Caching
{ {
fileDb.Clean(); fileDb.Clean();
} }
catch catch (Exception ex)
{ {
CheckReindex(); Trace.TraceWarning("FileDbCache: FileDb.Clean() failed: {0}", ex.Message);
} }
} }
public void Dispose() public void Dispose()
{
try
{
fileDb.DeleteRecords(new FilterExpression(expiresField, DateTime.UtcNow, EqualityEnum.LessThanOrEqual));
Trace.TraceInformation("FileDbCache has deleted {0} expired items", fileDb.NumDeleted);
fileDb.Clean();
fileDb.Close();
}
catch
{
if (CheckReindex())
{
fileDb.Close();
}
}
}
private bool CheckReindex()
{ {
if (fileDb.IsOpen) if (fileDb.IsOpen)
{ {
Trace.TraceWarning("FileDbCache is reindexing the cache database"); try
fileDb.Reindex(); {
return true; fileDb.DeleteRecords(new FilterExpression(expiresField, DateTime.UtcNow, EqualityEnum.LessThanOrEqual));
} Trace.TraceInformation("FileDbCache: Deleting {0} expired items", fileDb.NumDeleted);
fileDb.Clean();
}
catch
{
fileDb.Reindex();
}
return false; fileDb.Close();
}
} }
private void CreateDatebase() private void CreateDatebase()

View file

@ -1,4 +1,8 @@
using System; // WPF MapControl - http://wpfmapcontrol.codeplex.com/
// Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.ComponentModel; using System.ComponentModel;
using System.Globalization; using System.Globalization;
using System.Windows; using System.Windows;

View file

@ -1,4 +1,8 @@
using System; // WPF MapControl - http://wpfmapcontrol.codeplex.com/
// Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows; using System.Windows;
using System.Windows.Media.Animation; using System.Windows.Media.Animation;

View file

@ -1,4 +1,8 @@
using System; // WPF MapControl - http://wpfmapcontrol.codeplex.com/
// Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;

View file

@ -2,12 +2,10 @@
// Copyright © 2012 Clemens Fischer // Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL) // Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
namespace MapControl namespace MapControl
{ {

View file

@ -5,7 +5,6 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media;
namespace MapControl namespace MapControl
{ {

View file

@ -2,7 +2,6 @@
// Copyright © 2012 Clemens Fischer // Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL) // Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows; using System.Windows;

View file

@ -4,7 +4,6 @@
using System; using System;
using System.Windows; using System.Windows;
using System.Windows.Media;
namespace MapControl namespace MapControl
{ {

View file

@ -1,4 +1,7 @@
using System; // WPF MapControl - http://wpfmapcontrol.codeplex.com/
// Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;

View file

@ -3,12 +3,11 @@
// Licensed under the Microsoft Public License (Ms-PL) // Licensed under the Microsoft Public License (Ms-PL)
using System; using System;
using System.Collections.Generic; using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Windows; using System.Windows;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using System.Collections;
namespace MapControl namespace MapControl
{ {

View file

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -11,7 +12,6 @@ using System.Net;
using System.Runtime.Caching; using System.Runtime.Caching;
using System.Threading; using System.Threading;
using System.Windows; using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Threading; using System.Windows.Threading;
@ -48,19 +48,52 @@ namespace MapControl
/// <summary> /// <summary>
/// The time interval after which cached images expire. The default value is 30 days. /// The time interval after which cached images expire. The default value is 30 days.
/// When an image is not retrieved from the cache during this interval it is considered /// When an image is not retrieved from the cache during this interval it is considered
/// as expired and will be removed from the cache. If an image is retrieved from the cache /// as expired and will be removed from the cache. If an image is retrieved from the
/// and the CacheUpdateAge time interval has expired, the image is downloaded again and /// cache and the CacheUpdateAge time interval has expired, the image is downloaded
/// rewritten to the cache with new expiration time. /// again and rewritten to the cache with a new expiration time.
/// </summary> /// </summary>
public static TimeSpan CacheExpiration { get; set; } public static TimeSpan CacheExpiration { get; set; }
/// <summary> /// <summary>
/// The time interval after which a cached image is updated and rewritten to the cache. /// The time interval after which a cached image is updated and rewritten to the cache.
/// The default value is one day. This time interval should be shorter than the value of /// The default value is one day. This time interval should be shorter than the value
/// the CacheExpiration property. /// of the CacheExpiration property.
/// </summary> /// </summary>
public static TimeSpan CacheUpdateAge { get; set; } public static TimeSpan CacheUpdateAge { get; set; }
/// <summary>
/// Creates an instance of the ObjectCache-derived type T and sets the static Cache
/// property to this instance. Class T must (like System.Runtime.Caching.MemoryCache)
/// provide a constructor with two parameters, first a string that gets the name of
/// the cache instance, second a NameValueCollection that gets the config parameter.
/// If config is null, a new NameValueCollection is created. If config does not already
/// contain an entry with key "directory", a new entry is added with this key and a
/// value that specifies the path to an application data directory where the cache
/// implementation may store persistent cache data files.
/// </summary>
public static void CreateCache<T>(NameValueCollection config = null) where T : ObjectCache
{
if (config == null)
{
config = new NameValueCollection(1);
}
if (config["directory"] == null)
{
config["directory"] = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "MapControl");
}
try
{
Cache = (ObjectCache)Activator.CreateInstance(typeof(T), "TileCache", config);
}
catch (Exception ex)
{
Trace.TraceWarning("Could not create instance of type {0} with String and NameValueCollection constructor parameters: {1}", typeof(T), ex.Message);
throw;
}
}
static TileImageLoader() static TileImageLoader()
{ {
Cache = MemoryCache.Default; Cache = MemoryCache.Default;
@ -77,7 +110,7 @@ namespace MapControl
}; };
} }
public TileImageLoader(TileLayer tileLayer) internal TileImageLoader(TileLayer tileLayer)
{ {
this.tileLayer = tileLayer; this.tileLayer = tileLayer;
} }
@ -128,7 +161,7 @@ namespace MapControl
} }
else if (!CreateTileImage(tile, cachedImage.ImageBuffer)) else if (!CreateTileImage(tile, cachedImage.ImageBuffer))
{ {
// got garbage from cache // got corrupted buffer from cache
Cache.Remove(key); Cache.Remove(key);
pendingTiles.Enqueue(tile); pendingTiles.Enqueue(tile);
} }
@ -215,28 +248,28 @@ namespace MapControl
TraceInformation("{0} - Completed", tile.Uri); TraceInformation("{0} - Completed", tile.Uri);
} }
catch (WebException exc) catch (WebException ex)
{ {
buffer = null; buffer = null;
if (exc.Status == WebExceptionStatus.ProtocolError) if (ex.Status == WebExceptionStatus.ProtocolError)
{ {
TraceInformation("{0} - {1}", tile.Uri, ((HttpWebResponse)exc.Response).StatusCode); TraceInformation("{0} - {1}", tile.Uri, ((HttpWebResponse)ex.Response).StatusCode);
} }
else if (exc.Status == WebExceptionStatus.RequestCanceled) // by HttpWebRequest.Abort in CancelDownloadTiles else if (ex.Status == WebExceptionStatus.RequestCanceled) // by HttpWebRequest.Abort in CancelDownloadTiles
{ {
TraceInformation("{0} - {1}", tile.Uri, exc.Status); TraceInformation("{0} - {1}", tile.Uri, ex.Status);
} }
else else
{ {
TraceWarning("{0} - {1}", tile.Uri, exc.Status); TraceWarning("{0} - {1}", tile.Uri, ex.Status);
} }
} }
catch (Exception exc) catch (Exception ex)
{ {
buffer = null; buffer = null;
TraceWarning("{0} - {1}", tile.Uri, exc.Message); TraceWarning("{0} - {1}", tile.Uri, ex.Message);
} }
if (request != null) if (request != null)
@ -267,9 +300,9 @@ namespace MapControl
Dispatcher.BeginInvoke((Action)(() => tile.Image = bitmap)); Dispatcher.BeginInvoke((Action)(() => tile.Image = bitmap));
} }
catch (Exception exc) catch (Exception ex)
{ {
TraceWarning("Creating tile image failed: {0}", exc.Message); TraceWarning("Creating tile image failed: {0}", ex.Message);
return false; return false;
} }

View file

@ -4,7 +4,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Markup; using System.Windows.Markup;
using System.Windows.Media; using System.Windows.Media;

View file

@ -2,9 +2,7 @@
// Copyright © 2012 Clemens Fischer // Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL) // Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Windows.Media;
namespace MapControl namespace MapControl
{ {

View file

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="SampleApplication.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<SampleApplication.Properties.Settings>
<setting name="UsePersistentCache" serializeAs="String">
<value>True</value>
</setting>
</SampleApplication.Properties.Settings>
</applicationSettings>
</configuration>

View file

@ -1,13 +1,9 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media;
using MapControl;
using Caching; using Caching;
using MapControl;
namespace SampleApplication namespace SampleApplication
{ {
@ -15,13 +11,9 @@ namespace SampleApplication
{ {
public MainWindow() public MainWindow()
{ {
bool usePersistentCache = false; if (Properties.Settings.Default.UsePersistentCache)
if (usePersistentCache)
{ {
string appDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); TileImageLoader.CreateCache<FileDbCache>();
string cachePath = Path.Combine(appDataFolder, "MapControl", "Cache.fdb");
TileImageLoader.Cache = new FileDbCache("MapControlCache", cachePath) { AutoFlush = false };
} }
InitializeComponent(); InitializeComponent();

View file

@ -0,0 +1,35 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.225
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SampleApplication.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
[global::System.Configuration.ApplicationScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool UsePersistentCache {
get {
return ((bool)(this["UsePersistentCache"]));
}
}
}
}

View file

@ -0,0 +1,9 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="SampleApplication.Properties" GeneratedClassName="Settings">
<Profiles />
<Settings>
<Setting Name="UsePersistentCache" Type="System.Boolean" Scope="Application">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings>
</SettingsFile>

View file

@ -54,6 +54,11 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</ApplicationDefinition> </ApplicationDefinition>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Include="SampleItems.cs" /> <Compile Include="SampleItems.cs" />
<Page Include="MainWindow.xaml"> <Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -84,6 +89,13 @@
<Name>MapControl</Name> <Name>MapControl</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
// associated with an assembly. // associated with an assembly.
[assembly: AssemblyTitle("SurfaceApplication")] [assembly: AssemblyTitle("SurfaceApplication")]
[assembly: AssemblyDescription("WPF Map Control Sample SurfaceApplication")] [assembly: AssemblyDescription("WPF Map Control Sample Surface Application")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyProduct("WPF Map Control")] [assembly: AssemblyProduct("WPF Map Control")]