ZIndex of pushpins in WP7 bing map control - silverlight

I have a Bing silverlight map control for Windows phone 7. I am trying to display on top currently selected pushpin. Here is the snippet:
<my:Map x:Name="map" Canvas.ZIndex="1" CredentialsProvider="{StaticResource Credentials}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
CopyrightVisibility="Collapsed" LogoVisibility="Collapsed">
<my:MapItemsControl x:Name="Pushpins">
<my:MapItemsControl.ItemTemplate >
<DataTemplate>
<my:Pushpin Location="{Binding Location}" Canvas.ZIndex="{Binding Zindex}" PositionOrigin="0.515625,0.859375" Content="{Binding Id}" Template="{StaticResource PushpinControlTemplate}" Tap="Pushpin_Tap"/>
</DataTemplate>
</my:MapItemsControl.ItemTemplate>
</my:MapItemsControl>
</my:Map>
The control is ignoring the ZIndex. Am I missing something or the ZIndex is not supported. The ZIndex is property of a class which implements INotifyPropertyChanged
private int _zIndex;
public int Zindex
{
get { return _zIndex; }
set
{
_zIndex = value;
OnPropertyChanged(new PropertyChangedEventArgs("Zindex"));
}
}

I had the same problem where I had multiple pushpins close together and the problem was exacerbated when I had additional content to show when the pushpin was clicked.
The way I got around this problem was to remove the pushpin and then re-add it. That way it became the topmost pushpin.
map1.Children.Remove(pushpin);
map1.Children.Add(pushpin);

In a recent project I used two map layers to achieve this. The first map layer was bound to my list of pushpins ("resultsLayer"), the 2nd map layer was bound to a single 'SelectedItem' ("selectedLayer") on my view model.
The 2nd map layer will render on top of the first one. So, when a pushpin on the first layer was selected, it was removed from the collection (consequently removed from the layer) and set to be the selected pin which added it to the 2nd layer. The puspin control template for the 2nd layer contained the 'callout' which in my case was a button with some text in it that the user could click to open another page.
Here is my xaml:
<m:Map CredentialsProvider="xxxx" x:Name="map" Center="{Binding MapCenter, Mode=TwoWay}" ZoomLevel="{Binding MapZoomLevel, Mode=TwoWay}">
<m:MapLayer x:Name="resultsLayer" Visibility="{Binding IsBusy, Converter={StaticResource booleanNotCollapsedConverter}}">
<m:MapItemsControl ItemsSource="{Binding VenuesFound}">
<m:MapItemsControl.ItemTemplate>
<DataTemplate>
<m:Pushpin Location="{Binding VLocation}" PositionOrigin="BottomCenter" >
<m:Pushpin.Template>
<ControlTemplate>
<Image x:Name="mapPin" Grid.Row="1" Source="{Binding MapPin}" Stretch="None" />
</ControlTemplate>
</m:Pushpin.Template>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<gs:EventToCommand Command="{Binding SelectPinCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</m:Pushpin>
</DataTemplate>
</m:MapItemsControl.ItemTemplate>
</m:MapItemsControl>
</m:MapLayer>
<m:MapLayer x:Name="selectedLayer" DataContext="{Binding SelectedV}" Visibility="{Binding IsBusy, Converter={StaticResource booleanNotCollapsedConverter}}">
<m:Pushpin Location="{Binding VLocation}" PositionOrigin="BottomCenter">
<m:Pushpin.Template>
<ControlTemplate>
<StackPanel>
<Button Style="{StaticResource PushPinCallout}" Command="{Binding SelectItemCommand}">
<TextBlock Text="{Binding Name}" Foreground="White" Margin="2" TextWrapping="Wrap" />
</Button>
<Image x:Name="mapPin" Grid.Row="1" Source="{Binding MapPin}" Stretch="None" />
</StackPanel>
</ControlTemplate>
</m:Pushpin.Template>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Tap">
<gs:EventToCommand Command="{Binding SelectPinCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</m:Pushpin>
</m:MapLayer>
</m:Map>

As the BingMapsControl is not a Silverlight control it does not have any concept of a canvas.
Instead of trying to ensure the selected one is at the front, I'd change the selected pin to be of a larger, more prominent style.
It doesn't make sense (to me) to be able to control the z-index of pins as doing so could create a scenario where a pin appears to be on top of another pin, rather than on the map.

Related

WPF (mvvm, caliburn.micro) button click inside a listview item

I have a simple listview and listviewitem structure.
The Heart of the ListView.xaml is like the following
<StackPanel>
<ListBox x:Name="Movies" SelectedItem="{Binding SelectedMovie}">
<ListBox.ItemTemplate>
<DataTemplate>
<v:ListItemView/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
and the heart of the ListTtemView.xaml is the following:
<StackPanel>
<TextBlock Text="{Binding Id}"/>
<TextBlock Text="{Binding Title}"/>
<Button cal:Message.Attach="RunOperation" cal:Action.TargetWithoutContext="{Binding ElementName=UserControl, Path=DataContext}" Content="Run"/>
</StackPanel>
in the ListViewItemViewModel, I have a method called RunOperation and the scenario is when the user clicks the button in a listviewitem, the method RunOperation should be called. However, I get an exception: 'No target found for method RunOperation.'
I have read that the caliburn micro doesn't work in a case like this and if this is the case, I realised that I still don't know how to make it work the simple WPF way.
Apparently, RunOperation method cannot be found so I tried few combinations of cal:Action.TargetWithoutContext="{Binding ...}" but no help.
Thanks
If someone is still looking for a solution, here is what I did, With reference to caliburn.micro and interactivity in the xaml like below,
xmlns:cal="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro.Platform"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<Button Content="Run">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="RunOperation">
<cal:Parameter Value="{Binding}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
The view model button click method will be
public void RunOperation(object obj)
{
//Do your things
}
Since your xaml involving button is not available in question, am not sure if you have already tried this, but following should help you hit the function on Button's click event.
<Button cal:Message.Attach="[Event Click] = [Action RunOperation]"/>
I don't know anything about caliburn.micro.
But the normal WPF approach would be this
Step 1:
Create a Command in your ViewModel
class ViewModel
{
...
public ICommand RunOperationCommand { get; }
...
}
Step 2: Bind to it
<Button Command="{Binding RunOperationCommand }" />
That's not the caliburn.micro solution. And I don't know if there is a valid caliburn.micro solution for situations like this.
But the following works:
<Button Command="{Binding DataContext.RunOperationCommand, RelativeSource={RelativeSource AncestorType=ListBox}}" />
I was having the same issue, plus I was trying to get around it using a normal WPF approach.
I had Buttons being created dynamically inside a List Control which a source of was Bindable Collection of Sensors (my class).
You need to make sure you add a reference to the "xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" and
"xmlns:cal="http://www.caliburnproject.org" on your UserControl or Window.
Can find all the information and examples on Caliburn Micro Docs:
CaliburnActions Docs
<UserControl x:Class="BeckerGasApp.Views.MapView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BeckerGasApp.Views"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cal="http://www.caliburnproject.org">
<Grid>
<Grid>
<ItemsControl x:Name="Sensors" Background="Transparent" ItemsSource="{Binding Path=Sensors, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate >
<Button Background="Transparent" Content="{Binding SensorName}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:ActionMessage MethodName="Sensor">
<cal:Parameter Value="{Binding SensorName}" />
</cal:ActionMessage>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Viewbox>
</Grid>
</UserControl>
To do it inside a listview I had the following extra tag cal:Action.Target to be able to access ÀctionMessage for an item in listview.
<ListView
x:Name="LV"
Background="Transparent"
BorderBrush="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListViewItem>
<Button x:Name="StartPage">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cal:Action.Target>
<cal:ActionMessage MethodName="StartPage">
<cal:Parameter Value="{Binding}" />
</cal:ActionMessage>
</cal:Action.Target>
</i:EventTrigger>
</i:Interaction.Triggers>
<Button.Template>
<ControlTemplate>
<StackPanel Width="210" Orientation="Horizontal">
<Image Source="../Assets/img_home.png" Stretch="None" />
<TextBlock Style="{StaticResource font_style}" Text="Home" />
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
</ListViewItem>

DataGridTemplateColumn.CellTemplate How to add Image conditionally and hide checkbox in same column cell

<c1:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="chkBxIsChecked" IsChecked="{Binding IsChecked, Mode=TwoWay}" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="{Binding IsVisible, Mode=TwoWay}" >
<Image Name="ErrorImage" Visibility ="{Binding IsImgVisible, Mode=TwoWay}" Source= "../../../Resources/Images/Fail.png" Height="16" Width="16" Margin="5,0,0,0"></Image>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<t:MapEventToCommand Command="{Binding Source={StaticResource TestVM},Path=IsCkCommand}" CommandParameter="checked" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<t:MapEventToCommand Command="{Binding Source={StaticResource TestVM},Path=IsCkCommand}" CommandParameter="unchecked" />
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</c1:DataGridTemplateColumn.CellTemplate>
</c1:DataGridTemplateColumn>
I want to hide a check box in column and display image based on the data from db .
I was trying the above approach , but unable to display the image when i made visibility.collapse for the checkbox .
can i do that from codebehind ? , please suggest me .
Test one record in the attched image i am expecting to display image instead of checkbo ,where as it is showing empty because i made visibility collapsed against the row .
Thanks in advance .
You have added Image as child of CheckBox. So, making parent (CheckBox) collapsed will eventually make child (image) collapsed. Make checkBox and Image as siblings of parent container.
Replace
<CheckBox>
<Image/>
</CheckBox>
with
<Grid>
<CheckBox/>
<Image/>
<Grid>
Assuming Visibility bindings working fine.

ContextMenu not appearing when clicking on 'empty space' within StackPanel

I have a HierarchicalDataTemplate which has some simple Items contained in a horizontal StackPanel.
A context menu is assigned to the root StackPanel container as well:
<HierarchicalDataTemplate DataType="{x:Type data:GroupViewModel}"
ItemsSource="{Binding Path=Children}">
<StackPanel Orientation="Horizontal" Margin="2" ContextMenuOpening="groupContextMenuOpening">
<StackPanel.ContextMenu>
<StaticResource ResourceKey="groupContextMenu" />
</StackPanel.ContextMenu>
<Rectangle Width="16" Height="15" Fill="{Binding Converter={StaticResource HierarchyLevelConverter}}" Margin="0 0 3 0" Cursor="Hand" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown" >
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding SetCurrent}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Rectangle>
<Image Width="16" Height="15" Source="{Binding Path=GroupState, Converter={StaticResource GroupStateConverter}}" Cursor="Hand" Margin="0 0 3 0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown" >
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding ToggleGroupState}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
</StackPanel>
</HierarchicalDataTemplate>
The host TreeView also uses a ContextMenu.
The idea is that if you right click on an item in the TreeView, you will get it's ContextMenu.
If you right clik in empty space in the tree view you will get the 'default' context menu with lesser options.
This is all working expcept one odd problem.
As you can see the horizontal StackPanel leaves a margin between the images. If I right click in that space between items, the TreeView context menu shows up. I would expect the ContextMenu defined in my HierarchicalDataTemplate to pop up as i AM right click on the StackPanel itself.
I've found that if I assign a background color to the StackPanel it then works, but I would prefer to avoid this if possible.
Any ideas?
Set the Background of the StackPanel to Transparent to make it hit test in those empty areas.

Pattern for working with a form in Silverlight 4? (How to get references to XAML elements)

I have a form:
<StackPanel Orientation="Horizontal" Visibility="{Binding Editable, Converter={StaticResource visibilityConverter}}"
ToolTipService.ToolTip="Add new topic to this group">
<sdk:AutoCompleteBox Width="160" ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.TopicNames}" />
<Button Click="addTopicButton_Click">
<Image Source="Images/appbar.add.rest.png" />
</Button>
</StackPanel>
This form appears in a DataTemplate for an ItemsControl. I'm not sure what the best way is to get the data from the AutoCompleteBox when the button is clicked. I can't give the elements x:Name attributes, because they're in a template (right?).
How can I get around this? The Click event will give me the Button, but I need a reference to the text box. Use the Button's parent, then look through the children for the Textbox? If I factored this out into its own UserControl, I could set x:Name values, but I'd rather not do that.
Any other ideas?
Update: Here is another example of such a problem:
<ListBox x:Name="topicList"
ItemsSource="{Binding Id, Converter={StaticResource topicGroupIDConverter}}"
SelectionChanged="ListBox_SelectionChanged"
HorizontalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
Width="150"
VerticalAlignment="Center"
ToolTipService.ToolTip="{Binding Description}"
ToolTipService.Placement="Right" />
<Button ToolTipService.ToolTip="Remove this topic from this group"
Visibility="{Binding ElementName=topicList,
Path=DataContext.Editable,
Converter={StaticResource visibilityConverter}}"
Click="removeTopicButton_Click"
HorizontalAlignment="Right"
Margin="10,0">
<Image Source="Images/appbar.cancel.rest.png" />
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When the button is clicked, I want to access topicList.DataContext. However, topicList itself is a DataTemplate in an ItemsControl, so I can't access it using its name from code-behind. How else can I do this?
You can add a property, say SelectedItemInAutoCompleteBox, to your presenter, and then can bind it to the SelectedItem property of AutoCompleteBox, using Mode=TwoWay, like this,
<sdk:AutoCompleteBox SelectedItem="{Binding Path=DataContext.SelectedItemInAutoCompleteBox, Mode=TwoWay}" ... />
You may try the same approach with Text property of AutoCompleteBox, also. See if it solves your problem.:-)
You have several choices:
If you're on Silverlight 5, use the AncestorBinding
Otherwise, use a Silverlight 4 AncestorBinding hack (it doesn't look pretty)
Or you could try DataContextProxy, which stores the DataContext in a resource so that it is accessible. Note: you should set the DataContextProxy as a Resource of topicList ListBox, not the UserControl as in Dan Wahlin's example.

WPF ListBox DataTemplate and Image Question

I have a ListBox with a StackPanel that contains an image and label.
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding Image}" Cursor="Hand" Tag="{Binding Link}" MouseLeftButtonDown="Image_MouseLeftButtonDown" ToolTip="Click to see this product on adidas.com" VerticalAlignment="Top" HorizontalAlignment="Left" />
<Label Content="{Binding Name}" Cursor="Hand" Tag="{Binding Link}" MouseLeftButtonDown="Label_MouseLeftButtonDown" VerticalAlignment="Bottom" Foreground="White" Style="{StaticResource Gotham-Medium}" FontSize="8pt" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
I want to show a third image (glow.png) behind the currently moused over image. I can't seem to add a second image to the stack panel, and set it's visibility to hidden. I haven't even tackled the mouseover part yet.
Is adding another image inside the stack panel, and then setting it's visibility to visible the right approach on mouseenter, and then swapping back on mouseleave?
Thanks.
You certainly can have one image behind another. Instead of directly adding the image to your StackPanel, add a Grid and then add both images, like this:
<StackPanel Orientation="Vertical">
<Grid>
<Image Source="..." />
<Image Source="{Binding Image}" ... />
</Grid>
<Label Content="{Binding Name}" ... />
</StackPanel>
You might also like to look into Bitmap Effects, using which you can introduce a "glow" effect onto any WPF element.
Edit: Another way to achieve the effect you want (I believe) is to swap out the image's Source property in a trigger. I'm not going to try to write the XAML from memory here, but you could catch the IsMouseOver property for the image itself, and when it switches to True you could set its Source to the "glowing" version of the image.
Another possibility is to add a border to your image, set the color of the borderbrush to whatever you want and the opacity to 0. In your MouseEnter event handler set the opacity to 1.

Resources