====== Source Code ServicesEditionSample CachedValueStyle CS 090728.zip ====== ====CachedValueStyle.cs==== using System; using System.Collections.Generic; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace CachedValueStyle { // Mark the class Serializable so that it workes in SQL Server state // and in every serialization context [Serializable] public class CachedValueStyle : Style { private string columnName; private Dictionary valueItems = new Dictionary(); private Dictionary valuesCache = new Dictionary(); public CachedValueStyle() : this(string.Empty, new Dictionary()) { } public CachedValueStyle(string columnName, Dictionary valueItems) { this.columnName = columnName; this.valueItems = valueItems; } public string ColumnName { get { return columnName; } set { columnName = value; } } // We use a dictionary now instead of a collection to make lookups faster. public Dictionary ValueItems { get { return valueItems; } } // Here you can pre-load all of the values by feature Id. // The key is the Feature.Id and the value is the value to match the // value on. public Dictionary ValuesCache { get { return valuesCache; } } protected override void DrawCore(IEnumerable features, GeoCanvas canvas, Collection labelsInThisLayer, Collection labelsInAllLayers) { foreach (Feature feature in features) { string fieldValue = string.Empty; // If we have items field value in the cache then let's use them! // If not then get the value from the feature's column values if (valuesCache.Count == 0) { fieldValue = feature.ColumnValues[columnName].Trim(); } else { if (!ValuesCache.TryGetValue(feature.Id, out fieldValue)) { fieldValue = string.Empty; } } ValueItem valueItem = null; // Check if the there is a value item in the dictionary that matches // our field value. if (valueItems.ContainsKey(fieldValue)) { valueItem = valueItems[fieldValue]; } // If we cannot find a matcing value item in the collection do not draw anything. if (valueItem != null) { // Call the draw on all of the default styles of the value item and also // check if there are custom styles Feature[] tmpFeatures = new Feature[1] { feature }; if (valueItem.CustomStyles.Count == 0) { valueItem.DefaultAreaStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); valueItem.DefaultLineStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); valueItem.DefaultPointStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); valueItem.DefaultTextStyle.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); } else { foreach (Style style in valueItem.CustomStyles) { style.Draw(tmpFeatures, canvas, labelsInThisLayer, labelsInAllLayers); } } } } } protected override Collection GetRequiredColumnNamesCore() { Collection requiredFieldNames = new Collection(); // If we have provided cached values then there is no need to fetch the // column from our feature source. if (valuesCache.Count == 0) { requiredFieldNames.Add(columnName); } foreach (ValueItem valueItem in valueItems.Values) { // Check if we need any columns from custom styles foreach (Style style in valueItem.CustomStyles) { Collection tmpCollection = style.GetRequiredColumnNames(); foreach (string name in tmpCollection) { if (!requiredFieldNames.Contains(name)) { requiredFieldNames.Add(name); } } } // Check if we need any columns from the DefaultTextStyle Collection fieldsInTextStyle = valueItem.DefaultTextStyle.GetRequiredColumnNames(); foreach (string fieldName in fieldsInTextStyle) { if (!requiredFieldNames.Contains(fieldName)) { requiredFieldNames.Add(fieldName); } } // Check if we need any columns from the DefaultPointStyle Collection fieldsInPointStyle = valueItem.DefaultPointStyle.GetRequiredColumnNames(); foreach (string fieldName in fieldsInPointStyle) { if (!requiredFieldNames.Contains(fieldName)) { requiredFieldNames.Add(fieldName); } } // Check if we need any columns from the DefaultLineStyle Collection fieldsInLineStyle = valueItem.DefaultLineStyle.GetRequiredColumnNames(); foreach (string fieldName in fieldsInLineStyle) { if (!requiredFieldNames.Contains(fieldName)) { requiredFieldNames.Add(fieldName); } } // Check if we need any columns from the DefaultAreaStyle Collection fieldsInAreaStyle = valueItem.DefaultAreaStyle.GetRequiredColumnNames(); foreach (string fieldName in fieldsInAreaStyle) { if (!requiredFieldNames.Contains(fieldName)) { requiredFieldNames.Add(fieldName); } } } return requiredFieldNames; } } } ====Program.cs==== using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace CachedValueStyle { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new TestForm()); } } } ====TestForm.cs==== using System; using System.Drawing; using System.Windows.Forms; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace CachedValueStyle { public partial class TestForm : Form { private MapEngine mapEngine = new MapEngine(); private Bitmap bitmap = null; private ShapeFileFeatureLayer worldLayer = null; public TestForm() { InitializeComponent(); } private void TestForm_Load(object sender, EventArgs e) { // Set the full extent and the background color mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-180.0, 83.0, 180.0, -90.0), Map.Width, Map.Height); mapEngine.BackgroundFillBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean); // Add the static layers to the MapEngine worldLayer = new ShapeFileFeatureLayer(@"..\..\Data\Countries02.shp", ShapeFileReadWriteMode.ReadOnly); worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.County1; worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add("WorldLayer", worldLayer); ShapeFileFeatureLayer worldCapitalsLayer = new ShapeFileFeatureLayer(@"..\..\Data\WorldCapitals.shp", ShapeFileReadWriteMode.ReadOnly); CachedValueStyle cachedValueStyle = new CachedValueStyle(); cachedValueStyle.ColumnName = "pop_rank"; // Build the cache. Normally this would come from SQl or someplace else worldCapitalsLayer.Open(); Collection features = worldCapitalsLayer.FeatureSource.GetAllFeatures(new string[] { "pop_rank" }); foreach (Feature feature in features) { cachedValueStyle.ValuesCache.Add(feature.Id, feature.ColumnValues["pop_rank"].ToString()); } worldCapitalsLayer.Close(); cachedValueStyle.ValueItems.Add("1", new ValueItem("1", PointStyles.Capital1)); cachedValueStyle.ValueItems.Add("2", new ValueItem("2", PointStyles.Capital2)); cachedValueStyle.ValueItems.Add("3", new ValueItem("3", PointStyles.Capital3)); worldCapitalsLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Clear(); worldCapitalsLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(cachedValueStyle); worldCapitalsLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add("WorldCapitals", worldCapitalsLayer); DrawImage(); } private void DrawImage() { if (bitmap != null) { bitmap.Dispose(); } bitmap = new Bitmap(Map.Width, Map.Height); mapEngine.OpenAllLayers(); mapEngine.DrawStaticLayers(bitmap, GeographyUnit.DecimalDegree); mapEngine.DrawDynamicLayers(bitmap, GeographyUnit.DecimalDegree); mapEngine.CloseAllLayers(); Map.Image = bitmap; } private void ToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e) { switch (e.Button.Tag.ToString()) { case "Zoom In": mapEngine.CurrentExtent.ScaleDown(50); break; case "Zoom Out": mapEngine.CurrentExtent.ScaleUp(50); break; case "Full Extent": mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-180.0, 83.0, 180.0, -90.0), Map.Width, Map.Height); break; case "Pan Left": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Left, 20); break; case "Pan Right": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Right, 20); break; case "Pan Up": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Up, 20); break; case "Pan Down": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Down, 20); break; default: break; } DrawImage(); } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } } }