John,
There are a few different ways to get the effect you want. The first is to create your own custom style, it is ironic because we just sent out some details on a webinar to cover this. Below is some sample code on just how to do this, in the webinar we go into more detail on what is going on but I think you will see the main thrust of the code.
On thing to note is that in the sample I provided I was not able to test it so there may be a little bug here ot there but it isn't allot of code. Also I have no idea what these columns mean so for my example I just used the names you provided. If you want a much better version I would suggest you allow the user to set the column names maybe and give them human readable names. Since this is really specific to your case hard coding field names etc might not be that bad. What I hope you get out of this is how you can easily create your own Style classes based on complex logic. You can create a whole army of these kinds of Style classes tailored to your application.
On thing this makes me thing of though is that it would be handy to have an ExpressionStyle where the syntax looked something like “[LN_RTID] < 950000 && [LN_OW] == 0 && [LN_GC] == 1”. At runtime we would replace the column names with the real values and then pass the string to .net to execute it real-time and give us the answer. I will look into this today and see what I can dig up, this might be easy to implement and very powerful because then you could use logical AND, OR etc. I might be a bit slow to do but let me check into it. Thank you very much for sparking this idea!!
The other way is to use the styles we already have. The styles are composable meaning you can stack them inside of each other. For example you have use a ClassBreakStyle to handle the > 950,000 part and then for the style to draw inside of that class break you can place a ValueStyle to handle the other two parts. One other little trick is that in the system when you specify a field name that name can be composed of multiple fields. You can use the following syntax: “field1”, this gives you one field or you can use “[field1][field2]” and when we get the values we will parse out things inside the brackets and bet both fields and combine them. You can also do things like this “[SchoolName] is a great school in [SchoolCityName].” so if you have SchoolName and SchoolCityName as columns you might get a string returned like “Oak Hill is a great school in Sydney”. You can use this for labeling, styles or just about anywhere else that we take a field name as a parameter. If you find a place this isn't true then it is a bug on our part.
David
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
namespace CustomStyles
{
[Serializable]
class JohnCustomStyle : Style
{
private Style displayStyle;
private int rtId;
private int ow;
private int gc;
public JohnCustomStyle()
: this(0, 0, 0, new PointStyle())
{ }
public JohnCustomStyle(int rtId, int ow, int gc, Style displayStyle)
{
this.rtId = rtId;
this.ow = ow;
this.gc = gc;
this.displayStyle = displayStyle;
}
// This is the style you want to use if everything is correct
public Style DisplayStyle
{
get { return displayStyle; }
set { displayStyle = value; }
}
// Here you can put in your value for RTID
public int RtId
{
get { return rtId; }
set { rtId = value; }
}
// Here you can put in your value for OW
public int Ow
{
get { return ow; }
set { ow = value; }
}
// Here you can put in your value for GC
public int Gc
{
get { return gc; }
set { gc = value; }
}
// This is where the main logic is and there is not much. Loop through
// all the features and grab the column values you need. Check to see if
// the values match up with the values you have in the properties
// If they do then draw them using the DisplayStyle.
protected override void DrawCore(IEnumerable<Feature> features, GeoCanvas canvas, Collection<SimpleCandidate> labelsInThisLayer, Collection<SimpleCandidate> labelsInAllLayers)
{
foreach (Feature feature in features)
{
int lnRtId = Convert.ToInt32(feature.ColumnValues["LN_RTID"]);
int lnOw = Convert.ToInt32(feature.ColumnValues["LN_OW"]);
int lnGc = Convert.ToInt32(feature.ColumnValues["LN_GC"]);
if (lnRtId < rtId && lnOw == ow && lnGc == gc)
{
displayStyle.Draw(new Collection<Feature>() { feature }, canvas, labelsInThisLayer, labelsInAllLayers);
}
}
}
// This is a little tricky but really straight forward once you understand it.
// Here we get the columsn required from the DisplayStlye, if any.
// Next we add the three column names you need. This method is to
// make sure the fields you require are present when you get the feature
// in the DrawCore. We only return column values that are required
// for performance. If you do not specify the fields you need then they will
// not be on the feauture and you will get an exception.
protected override Collection<string> GetRequiredColumnNamesCore()
{
Collection<string> columns = new Collection<string>();
Collection<string> displayStyleColumns = displayStyle.GetRequiredColumnNames();
foreach (string column in displayStyleColumns)
{
if (!columns.Contains(column))
{
columns.Add(column);
}
}
if (!columns.Contains("LN_RTID"))
columns.Add("LN_RTID");
if (!columns.Contains("LN_OW"))
columns.Add("LN_OW");
if (!columns.Contains("LN_GC"))
columns.Add("LN_GC");
return columns;
}
// This just passes the DrawSample request to the display style.
protected override void DrawSampleCore(GeoCanvas canvas)
{
displayStyle.DrawSample(canvas);
}
}
}