In my UWP app I want user to allow select map element (to see detailed info) and unselect the map element by clicking empty are of the map.
In MapControl there are two events which I try to use:
MapElementClick(MapControl sender, MapElementClickEventArgs args)
This event is fired when user clicks map element, I can handle map element selection here.
MapTapped(MapControl sender, MapInputEventArgs args)
This event is fired when user tap's map. I could handle map element unselection here but the problem is that this event is also fired when map element is tapped.
How I should handle this map element unselection? I think there is no way how I can cancel click/tap event bubble from MapElementClick() to prevent MapTapped() firing?
This is my first answer here and I'm also kind of a C# newbie so be gentle pls :D
I had the same problem, and this is the workaround i did: I created two grids over my MapControl, one with margin, this is where you can show the detailed information, and an outer grid, which will detect the tap outside the information grid:
<Grid>
<maps:MapControl
x:Name="MapControl"
MapElementClick="MapControl_MapElementClick"
MapServiceToken="YourMapToken">
<Grid Name="OverlayGrid"
Background="Transparent"
Visibility="Collapsed"
Tapped="OverlayGrid_Tapped"/>
<Grid Name="InfoGrid"
Margin="50,50,50,50"
BorderBrush="Firebrick"
BorderThickness="2"
Background="White"
Visibility="Collapsed"/>
</Grid>
In the codebehind:
private void MapControl_MapElementClick(MapControl sender, MapElementClickEventArgs args)
{
InfoGrid.Visibility = Visibility.Visible;
OverlayGrid.Visibility = Visibility.Visible;
}
private void OverlayGrid_Tapped(object sender, TappedRoutedEventArgs e)
{
InfoGrid.Visibility = Visibility.Collapsed;
OverlayGrid.Visibility = Visibility.Collapsed;
}
This way whatever MapElement you click on will show you the grid where you can show your detailed information for the specific Mapelement, and if you click outside, both will be hidden. Of course you can use any other layout control for showing the information you want.
Related
I have some StackPanels in a Grid. They are filled with Labels (height of all labels > displayable space). A possible XAML would be:
<Grid>
<StackPanel>
<Label Content="bla" Background="lime" />
<Label ...>
...
</StackPanel>
</Grid>
Every time the size of the Grid changes, I need to change the inner content of the StackPanel. I need to hide the overflowing Label that is only shown partly. To achieve this, I can use following solutions: with a Converter and make a new class that is inherited from StackPanel.
I want to create a different way by using an attached property. I have following code:
//DepProp OverflowVisibility (double), can save height value
public static void Initialized(DependencyObject pObject, DependencyPropertyChangedEventArgs e)
{
var panel = (pObject as Panel) //the StackPanel in this case
panel.SizeChanged += panel_updateInnerLayout;
}
static void panel_LayoutUpdated(object sender, EventArgs e)
{
var parent = sender as Panel;
if(parent != null)
foreach(FrameworkElement element in parent.Children)
{
var elementPos = element.TransformToAncestor(parent).Transform(new Point(0,0));
if(element.ActualHeight + elementPos.Y >
(double)parent.GetValue(OverflowVisibilityProperty))
element.Visibility = Visibility.Hidden;
else
element.Visibility = Visibility.Visible;
}
}
And an example for usage in XAML:
<Grid>
<ItemsControl>
<ItemsPanel>
<ItemsPanelTemplate>
<StackPanel own:OverflowVisibility.OverflowVisibility="{Binding Grid height}" />
</ItemsPanelTemplate>
</ItemsPanel>
</ItemsControl>
</Grid>
Every time the StackPanel changes it's size, I can update my labels with the panel_updateInnerLayout event handler. When the size of StackPanel is changed, everything is working fine.
My Problem: The StackPanel itself doesn't raise SizeChanged because it has a bigger height than the Grid. I need an event that raises every time the Grid changes its height.
My Question: Is there any event instead of SizeChanged, that is called every time I change the Grid size? If not, is there an alternative way with an attached property to solve my problem?
I also tried to set a binding of the height of the StackPanel to ItemsControl ActualHeight but it does not raise the SizeChanged.
Unfortunately, you have chosen the wrong Panel control for your requirements. The StackPanel should only be used when the resizing of its contents is not required, because it doesn't provide any child control resizing abilities. Therefore, you should use a Grid, or any other Panel that provides resizing abilities. Please refer to the Panels Overview page on MSDN for further help with choosing the appropriate Panel.
There are 2 possible events: SizeChanged and LayoutUpdated. SizeChanged doesn't work because the StackPanel is not resized. LayoutUpdated does not work, because the sender of this event is always null and i can not locate what StackPanel was the source.
For more see: Layout Events - SizeChanged and LayoutUpdated.
So there are no possible event available for my approach.
While I searched for a solution, I also found out, that I used the term attached property also for attached behavior and blend behavior. The difference is described here. Summary: properties do nothing with the object but their presence can be used, behaviours change the object behavior. Blend behaviors are behaviors that Microsoft created for Microsoft Blend. The code in my question is attached behavior.
For attached behaviors I didn't found a solution, but for Blend behaviors i found some. You need to add a reference Micosoft.Windows.Interactivity.
After that i used this code:
public class OverflowVisibilityBehavior : Behavior<VirtualizingStackPanel>
{
protected override void OnAttached()
{
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
}
void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
var parent = AssociatedObject; //that solves the problem: you can get a "sender" information
//...
// Instead of property GetValue
(VisualTreeHelper.GetParent(parent) as ItemsPresenter).ActualHeight
}
}
Some problems left: The parent of the StackPanel must raise SizeChanged. If you put a StackPanel in a StackPanel in a Grid, you need modify it.
Second: LayoutUpdated changes the StackPanel several times. More times than i need.
I have created a button using XAML and have defined some simple properties for it.
<Button Name="btnNext" Grid.Row="1" Content="PARA" Width="200" Grid.Column="1" Background="#FF2D2D2D" HorizontalAlignment="Right" FontSize="40" Height="380" BorderThickness="0" />
It happens that when I click on the button or put the mouse over, it changes color.
I have tried to escape this behaviour in the btnNext_Click method but it does not affect anything.
private void btnNext_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
button.Background = new SolidColorBrush(hexToColorConvertor("#FF2D2D2D"));
START_POINT += (uint)NUMBER_OF_BUTTONS1;
ReadFile(START_POINT);
}
}
Does anyone have any idea how to resolve this?
In XAML, button have default style for different states like Normal, MouseOver, Pressed etc..
Whenever button moves from one state to another, it changes its look using default style obviously. You can find more information related to default style here
Now, If you want to override this default behavior, you can do it easily with Expression-blend. More of this can be found here and here
Hope this information will help you.. :)
I load some quiz questions in one of my PivotItems.
My problem is when the user is in this PivotItem and if swipe to go to another PivotItem I want to get pop-up MessagePrompt before leaving this PivotItem to another, asking if the user really want to finish the quiz. I tried LostFocus event and Unloaded event but nothnig happens.
How can i manage this?
P.S. I know that the Quiz should be in another page, but I want to achieve this with pivotItems.
Subscribe to pivots selectionChanged event
Pivot_SelectionChanged Event
{
if(Pivot.selectedindex==1|| 3|| 4)
{
Messagebox();
}
}
Assuming 2 is your pivot items index.
now if the user chooses "yes" then assign pivots selectedindex to 2
You can subscribe to the SelectionChanged event whenever a PivotItem is changed. Check the link for some examples from MSDN.
http://msdn.microsoft.com/en-us/library/windowsphone/develop/microsoft.phone.controls.pivot.selectionchanged(v=vs.105).aspx
I haven't tried this out yet, but I believe the PivotItem will still change even when the pop-up occurs. So once you get the pop-up and you give the user a choice to stay on the current Pivot or go to the next, you might have to change the PivotItem programatically back to the quiz Pivot.
A slightly messy way would be to preserve the currently selected Pivot Index state, and subscribe to the DragStartedGestureEventArgs using the windows phone controls toolkit.
<controls:Pivot x:Name="pivotControl" Title="MY APPLICATION">
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener DragStarted="SelectedPivotChanging"></toolkit:GestureListener>
</toolkit:GestureService.GestureListener>
<controls:PivotItem Header="item1">
<Grid />
</controls:PivotItem>
<controls:PivotItem Header="item2">
<Grid/>
</controls:PivotItem>
</controls:Pivot>
private void SelectedPivotChanging(object sender, DragStartedGestureEventArgs e)
{
if (pivotControl.SelectedIndex == 0)
{
if (MessageBox.Show("Are you sure you wish to navigate away?", "Un-Answered questions", MessageBoxButton.OKCancel)
== MessageBoxResult.Cancel)
{
//pivotControl.SelectedIndex = previousIndex;
}
}
}
I'm creating a WPF application that use the Bing Maps. I put it in a page control that at the same time is called from an iframe control. At the begining it displayed the Map and I can zoom in and out without a problem.
The thing is, that when I click the Map with the left button of my mouse what it does is to go down a little bit of the current location and a zoom in is done automatically instead of holding the point where the click was done to do a kind of drag and drop. Just like Google Maps does.
Here is my XAML code:
<Grid x:Name="LayoutRoot">
<TextBlock Text="News page" FontSize="32" />
<m:Map CredentialsProvider="..."
Center="25.6732109,-100.309201" ZoomLevel="12" Mode="Road"/>
</Grid>
I'm using the following assembly reference: xmlns:m="clr-namespace:Microsoft.Maps.MapControl.WPF;assembly=Microsoft.Maps.MapControl.WPF"
Does any one know how can I fix it?
Regards!
If you use the mouse up or down events on the Map control this will work fine. The map itself doesn't expose a Click event of it's own, but you don't need that if you use the mouse up/down events.
I had the same problem. The solution was to add a MouseDown Event to the map:
<m:Map
CredentialsProvider="<your Credentials>"
Center="{Binding Center, Mode=TwoWay}"
ZoomLevel="10"
MouseDown="Map_MouseDown">
</m:Map>
In the code behind you can add:
private void Map_MouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
This handles the event and no further processing is done. After this moving and draging the Map worked as usual maps do.
I am trying to implement what I used to take for granted in Winforms applications. I am a Silverlight noob, so hopefully all this is elementary.
I have a listbox in a Silverlight 4 app. I'd like to do the following:
Right-click on the listbox
Have the item under the location where I click highlight itself
I'd like a context menu to popup (with my own items in the context menu)
From my research so far, it appears that there is no ContextMenu construct in Silverlight, instead we have to build up a Grid/Canvas structure and attach it to a Popup object, which is what is then popped up.
My questions are as follows:
To accomplish #2, I need some kind of hit test on the listbox. I can't figure out how to do that and my google-fu isn't helping.
Once I do identify the index under the mouse, how do I actually select the item?
Is there a reusable Context menu component somewhere that I can use? Extra credit if the component allows arbitrary sub-menus.
I've been looking around for the same thing. I checked the Silverlight Control Toolkit at CodePlex and went through the samples (it's a very handy resource) and here's what I found to be the solution to what you asked:
Create an ItemTemplate for your ListBox
in the part that you want to be "right-clickable" of your ItemTemplate set the attached property ContextMenuService.ContextMenu that exists within the System.Windows.Controls.Input.Toolkit namespace
add MenuItem controls to your ContextMenu and set the Click property to the corresponding click event handler
in the event handler, get the DataContext from the sender (you can use that to find the corresponding element in the ListBox)
to make that element Selected, just set the SelectedItem property in the list box to it
Add any custom logic to the event handler
There's an example in the samples page, just go to "Input->ContextMenu" from the navigation pane.
If you want something concise, Here's a simplified example:
<ListBox ItemsSource="{StaticResource People}"
Name="myListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<controlsInputToolkit:ContextMenuService.ContextMenu>
<controlsInputToolkit:ContextMenu>
<controlsInputToolkit:MenuItem Header="Show in MessageBox"
Click="show_Click" />
</controlsInputToolkit:ContextMenu>
</controlsInputToolkit:ContextMenuService.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
with:
xmlns:controlsInputToolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit"
for the code:
private void show_Click(object sender, RoutedEventArgs e)
{
var person = ((MenuItem)sender).DataContext as Person;
if (null == person) return;
MessageBox.Show("My Name is: " + person.Name);
myListBox.SelectedItem = person;
}
I hope this helps :)
There's the MouseRightButtonDown event. If you bind that on the ListBox:
<ListBox Height="143" Name="listBox1" Width="218"
MouseRightButtonDown="listBox1_MouseRightButtonDown" />
you'll get what you need. The code behind is:
private void listBox1_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
}
The MouseButtonEventArgs will give you the position via the GetPosition method.