区域显示
通过拿到地图上的经纬度集合,类似行政区划图的边缘点,然后将点作为边界点互相连接后,显示围成的这块封闭区域。
其中增加一个ContentControl
开放了区域内部,在控件外部可以根据控件自定义的依赖属性ItemTemplate
来自由定制数据内容。
<DataTemplate>
<Grid>
<Path Fill="{Binding Fill}" Stroke="{Binding BorderBrush}"
dependecys:PathDependency.Command="{Binding ClickCommand}"
dependecys:PathDependency.CommandParameter="{Binding Path=.}">
<Path.Data>
<MultiBinding Converter="{StaticResource AreaToPathData}">
<Binding Path="."></Binding>
<Binding Path="Points"></Binding>
<Binding Path="BaseMap.ModifyCount" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=UserControl}"></Binding>
<Binding Path="BaseMap" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=UserControl}"></Binding>
</MultiBinding>
</Path.Data>
</Path>
<ContentControl Content="{Binding Path=.}"
ContentTemplate="{Binding ItemTemplate,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}">
</ContentControl>
</Grid>
</DataTemplate>
这里最重要的就是根据几个绑定数据,改变Path的形状。用的如下转换器
public class AreaConvertToPathDataConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
Area area = values.First() as Area;
BaseMapLayout baseMap = values.Last() as BaseMapLayout;
List<Point> points = new List<Point>();
foreach (var item in area.Points)
{
points.Add(baseMap.LongitudeAndAtitudeConvertToCurrentPixel(item.X, item.Y));
}
area.OffsetX = points.Min(p => p.X);
area.OffsetY = points.Min(p => p.Y);
Point offset = new Point(area.OffsetX, area.OffsetY);
StreamGeometry geometries = new StreamGeometry();
using (var context = geometries.Open())
{
var item = points.First();
var p = Sub(item, offset);
context.BeginFigure(p, true, true);
for (int i = 1; i < points.Count; i++)
{
p = Sub(points[i], offset);
context.LineTo(p, true, true);
}
}
return geometries;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
/// <summary>
/// 相减
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
private Point Sub(Point p1, Point p2)
{
return new Point(p1.X - p2.X, p1.Y - p2.Y);
}
}
上面这个ItemsControl是显示瓦片地图的,下面这个ItemsControl就是显示区域的。
<Grid Canvas.Left="{Binding OffsetX,ElementName=MainControl}" Canvas.Top="{Binding OffsetY,ElementName=MainControl}"
MouseMove="MMove" MouseDown="MDown" MouseUp="MUp" MouseLeave="MLeave" MouseWheel="MWheel" >
<ItemsControl ItemsSource="{Binding BaseMap.TitleBlocks,ElementName=MainControl}"
ScrollViewer.CanContentScroll="False" Name="MapLayout"
Style="{StaticResource MapCanvasImageList}">
</ItemsControl>
<ItemsControl ItemsSource="{Binding Areas,ElementName=MainControl}"
ScrollViewer.CanContentScroll="False"
Style="{StaticResource MaskListStyle}"
></ItemsControl>
</Grid>
其中这个Style,将ItemsControl的ItemsPanel设置为Canvas,使用坐标控制。
<Style TargetType="ItemsControl" x:Key="MaskListStyle">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"></Canvas>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding OffsetX,Mode=TwoWay}"></Setter>
<Setter Property="Canvas.Top" Value="{Binding OffsetY,Mode=TwoWay}"></Setter>
</Style>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Path Fill="{Binding Fill}" Stroke="{Binding BorderBrush}"
dependecys:PathDependency.Command="{Binding ClickCommand}"
dependecys:PathDependency.CommandParameter="{Binding Path=.}">
<Path.Data>
<MultiBinding Converter="{StaticResource AreaToPathData}">
<Binding Path="."></Binding>
<Binding Path="Points"></Binding>
<Binding Path="BaseMap.ModifyCount" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=UserControl}"></Binding>
<Binding Path="BaseMap" RelativeSource="{RelativeSource Mode=FindAncestor,AncestorType=UserControl}"></Binding>
</MultiBinding>
</Path.Data>
</Path>
<ContentControl Content="{Binding Path=.}"
ContentTemplate="{Binding ItemTemplate,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}">
</ContentControl>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>