Bing 使用 C# 和 MVVM 信息框和图钉绑定的地图
Bing Maps with C# and MVVM Infobox and pushpin Bindings
我正在尝试为我的 Windows 8.1 程序实现地图屏幕,我正在使用 Bing 地图 API 以及 C# 和 MVVM。
我面临的问题:
首先,我可以在 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>
其次,如果我有一个在列表上绑定了多个图钉的地图,我如何为每个图钉添加 "Pushpin.Tapped" 事件调用一个方法来移动和设置 ViewModel 中的信息框可见?
目前我使用简单的代码隐藏(不是 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);
}
我需要从 ViewModel 完成这一切。
我是 MVVM 的新手,有人可以给我一些提示吗?
我一直在阅读有关 MVVM 的内容,有人说 View 应该负责所有表示交互,而 ViewModel 应该负责数据。
我用下面的结构让它工作:
查看:
<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>
查看代码隐藏:
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;
}
}
}
我的代码隐藏在 DataSource 更改后将事件 "Pushpin.Tapped" 添加到 "DataLayer" 中的所有引脚,并且还控制信息框的位置和可见性。
我认为这不是一种打破模式的方法,如果你们有任何建议或意见,我将很高兴听到。
我正在尝试为我的 Windows 8.1 程序实现地图屏幕,我正在使用 Bing 地图 API 以及 C# 和 MVVM。
我面临的问题:
首先,我可以在 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>
其次,如果我有一个在列表上绑定了多个图钉的地图,我如何为每个图钉添加 "Pushpin.Tapped" 事件调用一个方法来移动和设置 ViewModel 中的信息框可见? 目前我使用简单的代码隐藏(不是 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);
}
我需要从 ViewModel 完成这一切。 我是 MVVM 的新手,有人可以给我一些提示吗?
我一直在阅读有关 MVVM 的内容,有人说 View 应该负责所有表示交互,而 ViewModel 应该负责数据。
我用下面的结构让它工作:
查看:
<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>
查看代码隐藏:
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;
}
}
}
我的代码隐藏在 DataSource 更改后将事件 "Pushpin.Tapped" 添加到 "DataLayer" 中的所有引脚,并且还控制信息框的位置和可见性。 我认为这不是一种打破模式的方法,如果你们有任何建议或意见,我将很高兴听到。