简体   繁体   English

带有C#和MVVM信息框和图钉绑定的Bing映射

[英]Bing Maps with C# and MVVM Infobox and pushpin Bindings

I'm trying to implement a map screen for a Windows 8.1 program of mine and I'm using Bing Maps API with C# and MVVM. 我正在尝试为我的Windows 8.1程序实现地图屏幕,并且将Bing Maps API与C#和MVVM结合使用。

The problems I'm facing: 我面临的问题:

First, I am able to show the pushpin and the infobox on the map using binding in the xaml but when I move the map, the infobox remains in the same position (centered in that case), not following the pushpin or the map movement. 首先,我可以使用xaml中的绑定在地图上显示图钉和信息框,但是当我移动地图时,信息框保持在同一位置(在这种情况下居中),而不是跟随图钉或地图移动。

Here the xaml: 这里的xaml:

<bm:Map ZoomLevel="15" Height="500" Width="600" ShowTraffic="False" ShowScaleBar="False" ShowNavigationBar="False" ShowBreadcrumb="False" ShowBuildings="False"
            Credentials="xxxxxxx" Name="myMap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
        <bm:Map.Center>
            <bm:Location Latitude="-25.450520" Longitude="-49.251557" />
        </bm:Map.Center>

        <bm:Map.Children>

            <bm:MapLayer Name="DataLayer">
                <bm:Pushpin Style="{Binding PushpinStyle}">
                    <bm:MapLayer.Position>
                        <bm:Location Latitude="{Binding Establishment.Pin.Latitude, Mode=OneWay}" Longitude="{Binding Establishment.Pin.Longitude, Mode=OneWay}" />
                    </bm:MapLayer.Position>
                </bm:Pushpin>
            </bm:MapLayer>

            <bm:MapLayer Margin="5,0,0,0" Position="{Binding InfoboxPosition}" Height="Auto" Width="Auto" >
                <Grid x:Name="Infobox" Visibility="{Binding InfoboxVisibility}" Margin="35,0,0,0" Height="Auto" >
                    <Border MaxWidth="350" Style="{StaticResource InfoboxBorderStyle}" />
                    <StackPanel Margin="10" MinWidth="200" MaxWidth="350">
                        <Grid>
                            <TextBlock Text="{Binding Establishment.Name}" Style="{StaticResource InfoboxTitleStyle}" />
                        </Grid>
                        <TextBlock Text="{Binding EstablishmentAddress}" Style="{StaticResource InfoboxContentStyle}"  MaxWidth="290" Margin="7" />
                    </StackPanel>
                </Grid>
            </bm:MapLayer>

        </bm:Map.Children>

    </bm:Map>

Second, if I have a map with multiple pushpins binded on a list, how can I add the "Pushpin.Tapped" event for each pin calling a method to move and set visible the infobox from ViewModel? 其次,如果我的地图上绑定了多个图钉,则如何为每个图钉添加“ Pushpin.Tapped”事件,从而调用从ViewModel移动并设置可见信息框的方法? Currently I make it work using simple codebehind (not VM) with something like that: 目前,我使用诸如此类的简单代码隐藏(而非VM)使其工作:

public MapControl()
    {
        this.InitializeComponent();
        AddPushpin(new Location(-25.450520, -49.251557), "Title", "Description", DataLayer, EstablishmentKindEnum.Cinema);
    }

    private async void pushpinTapped(object sender, TappedRoutedEventArgs e)
    {
        Pushpin p = sender as Pushpin;
        PushpinMetadata m = (PushpinMetadata)p.Tag;

        //Ensure there is content to be displayed before modifying the infobox control
        if (!String.IsNullOrEmpty(m.Title) || !String.IsNullOrEmpty(m.Description))
        {
            Infobox.DataContext = m;
            Infobox.Visibility = Visibility.Visible;
            MapLayer.SetPosition(Infobox, MapLayer.GetPosition(p));
        }
        else
            Infobox.Visibility = Visibility.Collapsed;
    }

    private void CloseInfobox_Tapped(object sender, TappedRoutedEventArgs e)
    {
        Infobox.Visibility = Visibility.Collapsed;
    }

    public void AddPushpin(Location latlong, string title, string description, MapLayer layer, EstablishmentKindEnum kind)
    {
        var pushpin = MapHelper.CreatePushpin(latlong, title, description, kind);
        MapLayer.SetPosition(pushpin, latlong);
        pushpin.Tapped += pushpinTapped;
        layer.Children.Add(pushpin);
    }

I need to do it all from ViewModel. 我需要通过ViewModel完成所有操作。 I'm new on MVVM, anybody can give me some hints? 我是MVVM的新手,有人可以给我一些提示吗?

I've been reading about MVVM and some people says that the View should be responsible for all presentation interactions and the ViewModel should be responsible for the data. 我一直在阅读有关MVVM的信息,有人说View应该负责所有演示交互,而ViewModel应该负责数据。

I make it work with the structure below: 我将其与以下结构一起使用:

View: 视图:

<Grid>
    <bm:Map ZoomLevel="15" Height="500" Width="600" ShowTraffic="False" ShowScaleBar="False" ShowNavigationBar="False" ShowBreadcrumb="False" ShowBuildings="False"
            Credentials="xxxxxx" Name="myMap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DataContextChanged="Map_DataContextChanged">
        <bm:Map.Center>
            <bm:Location Latitude="-25.450520" Longitude="-49.251557" />
        </bm:Map.Center>

        <bm:Map.Children>

            <bm:MapLayer Name="DataLayer">
                <bm:Pushpin Style="{Binding PushpinStyle}">
                    <bm:MapLayer.Position>
                        <bm:Location Latitude="{Binding Establishment.Pin.Latitude, Mode=OneWay}" Longitude="{Binding Establishment.Pin.Longitude, Mode=OneWay}" />
                    </bm:MapLayer.Position>
                </bm:Pushpin>
            </bm:MapLayer>

            <bm:MapLayer Margin="5,0,0,0"  Height="Auto" Width="Auto" >
                <Grid x:Name="Infobox" Visibility="Collapsed" Margin="35,0,0,0" Height="Auto" >
                        <Border MaxWidth="350" Style="{StaticResource InfoboxBorderStyle}" />
                    <StackPanel Margin="10" MinWidth="200" MaxWidth="350">
                        <Grid>
                            <TextBlock Text="{Binding Establishment.Name}" Style="{StaticResource InfoboxTitleStyle}" />
                            <Button Tapped="CloseInfobox_Tapped" Style="{StaticResource InfoboxCloseButtonStyle}" />
                        </Grid>
                        <TextBlock Text="{Binding EstablishmentAddress}" Style="{StaticResource InfoboxContentStyle}"  MaxWidth="290" Margin="7" />
                    </StackPanel>
                </Grid>
            </bm:MapLayer>

        </bm:Map.Children>

    </bm:Map>
</Grid>

View CodeBehind: 查看代码背后:

public sealed partial class MapControl : UserControl
{
    public MapControl()
    {
        this.InitializeComponent();
    }

    private async void pushpinTapped(object sender, TappedRoutedEventArgs e)
    {
        Pushpin p = sender as Pushpin;
        Infobox.Visibility = Visibility.Visible;
        MapLayer.SetPosition(Infobox, MapLayer.GetPosition(p));
    }

    private void CloseInfobox_Tapped(object sender, TappedRoutedEventArgs e)
    {
        Infobox.Visibility = Visibility.Collapsed;
    }

    private void Map_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
    {
        if (DataLayer.Children != null)
            foreach (var pin in DataLayer.Children)
            {
                pin.Tapped += pushpinTapped;
            }
    }
}

My codebehind add the event "Pushpin.Tapped" to all pins in the "DataLayer" after the DataSource change, and also controls the position and visibility of the Infobox. 我的代码背后是在数据源更改后将事件“ Pushpin.Tapped”添加到“ DataLayer”中的所有图钉,并且还控制了信息框的位置和可见性。 I think that is not a pattern-breaking approach and if you guys have any suggestions or comments, I'll be glad to hear it. 我认为这不是打破模式的方法,如果你们有任何建议或意见,我将很高兴听到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM