WPF中手写地图控件(2)——区域显示

28 篇文章 3 订阅
4 篇文章 0 订阅

区域显示

通过拿到地图上的经纬度集合,类似行政区划图的边缘点,然后将点作为边界点互相连接后,显示围成的这块封闭区域。
其中增加一个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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值