How to use WPF Bing Map as DataTemplate? - c#

Using the Bing Maps WPF-SDK it is esy to integrate a map. But I would like to use the Bing-Map as DataTemplate for an ItemsControl element. If I do so, unfortunately, the maps object does not react to any bindings and it obviously does not accept the Credentials Key. My code is as follows:
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type s:Point}">
<ContentControl
Width="{Binding Width, Mode=TwoWay}"
Height="{Binding Height, Mode=TwoWay}"
Template="{StaticResource InteractiveItemTemplate}">
<m:Map Margin="5" ZoomLevel="5" CredentialsProvider="MyCredentials" />
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
Even the ZoomLevel of 5 is not used, the map is always in default view and it displays the "Invalid Credentials" message. How to use the map in a DataTemplate properly

Alright, so my own answer is: it seems not to work if one adds the code above directly in the MainViewWindow.xaml. But once I created an separate UserControl.xaml with the Map, I than use the UserControl as DataTemplate it works well.

Related

How to get MVVM Mouse Position Inside of TabControl.ContentTemplate to ViewModel?

I am creating a simple image editing-style app and am attempting to use MVVM for the first time. The idea is to parse proprietary text files and represent them visually in tabs within the app so they can be updated with paint strokes and the like before being converted back to text. In figuring out how to get mouse position to the view model, I found Mark Green's solution works well; however, I can't get it to work if I place it inside my TabControl.ContentTemplate - if I do so, the program crashes unceremoniously when I load the first text file (which creates the first tab). Here's the relevant section of code (see link for the code used in the ViewModels):
<Grid>
<!--If I stick the Interaction behavior here it works, but I get mouse position relative to entire grid-->
<TabControl ItemsSource="{Binding Maps}" SelectedIndex='{Binding TabIndex}'>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Image x:Name="imgMap" Source='{Binding Content}'>
<i:Interaction.Behaviors><!--Putting it here causes an unhandled exception-->
<local:MouseBehaviour MouseX="{Binding PanelX, Mode=OneWayToSource}"
MouseY="{Binding PanelY, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Image>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
As you can see from my comments in the code, my placement of the interaction behavior seems to be what is breaking the app. Since the exception occurs in external code, I can't figure out exactly what is wrong but I suspect it has something to do with the code being inside a template (please correct me if I am wrong!).
My question is this: how do I get interaction behaviors (and later triggers - I will want mouse button events as well) working within the template, or am I going about this the wrong way? Is there a better solution to get mouse position (relative to the image) to the ViewModel?
Many thanks in advance for any help offered!
UPDATE
Per STrenat's suggestion, I updated the MouseBehavior class to use UIElement instead of Panel:
public class MouseBehaviour : System.Windows.Interactivity.Behavior<UIElement>
{
// Rest of code from Mark Green's solution linked in original post
}
To get access to the mouse position values in the main window (instead of inside the ItemTemplate), I updated my bindings in the XAML (with output text blocks now shown) to point to properties in the main viewmodel (without the relative reference you have to have the properties inside the TabItem):
<StackPanel>
<TextBlock Text="{Binding PanelX, StringFormat='X={0:0}, '}" />
<TextBlock Text="{Binding PanelY, StringFormat='Y={0:0}'}" />
<TabControl ItemsSource="{Binding Maps}"
SelectedIndex='{Binding TabIndex}'>
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<Image x:Name="imgMap"
Source='{Binding Content}'>
<i:Interaction.Behaviors>
<local:MouseBehaviour MouseX="{Binding DataContext.PanelX, RelativeSource={RelativeSource AncestorType={x:Type Window}}, Mode=OneWayToSource}"
MouseY="{Binding DataContext.PanelY, RelativeSource={RelativeSource AncestorType={x:Type Window}}, Mode=OneWayToSource}" />
</i:Interaction.Behaviors>
</Image>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</StackPanel>
The rest is as specified in the solution referenced above. Hope that helps anybody else running into this problem!

Windows Phone 8.1 flow container for dynamic buttons

SOF Tribe,
I have a request for the identity of a flow container into which I can pour an indeterminate number of dynamically created XAML buttons. Said buttons should wrap the text as closely as possible (I think I have a template for this). But the buttons should wrap like a gridview, but run like a stackpanel. Does anyone know a container that will allow me to accomplish what the image portrays?
Currently, for the existing image below, I'm using a gridview, but the gridview sets a specific width but does flow unevenly. A stackpanel has the desired end-to-butt style but won't wrap. So, any ideas?
There is what is called the UniversalWrapPanel made by Greg Stoll. So, that's the direction I'll be taking. Now however, I've got the last little bit to tackle. How to get the bound data to respect the parent container's ability to wrap content and not just stack it up in a vertical column.
The below XAML gives me the below image result which is not quite what I want. Statically added buttons work just fine to the UniversalWrapPanel. But trying to get a binding and ItemsSource to work, well, that's beyond me at this time.
<support:UniversalWrapPanel Orientation="Horizontal" Background="White">
<ItemsControl x:Name="GridViewRecipients" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource ButtonLozengeStyle}" Content="{Binding FullName}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</support:UniversalWrapPanel>
OK, so a bit more searching and I found this:
http://www.visuallylocated.com/post/2015/02/20/Creating-a-WrapPanel-for-your-Windows-Runtime-apps.aspx
and so here is the correct way to reference the UniversalWrapPanel within the ItemsControl:
<ItemsControl x:Name="GridViewRecipients" ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<support:UniversalWrapPanel Orientation="Horizontal" Background="DodgerBlue"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource ButtonLozengeStyle}" Content="{Binding FullName}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
For the result of:

CollectionView with WPF (or something like that)

I've try to adopt the CollectionView of iOS on WPF. The background is the migration of an iOS App to a Windows Store App (Windows 10 Universal App).
I try to create a List of clickable objects which contain:
a label
a image
How can I do this? It should look like this:
http://i.stack.imgur.com/ETsqy.png
Can somebody give me an example of XAML code for my purpose?
Sure. Google for itemscontrol, there you get in "ItemsSource" a specific type of model (Class), and that class type is your itemscontrol dataContext.
in this control you can handle ItemTemplate in order to create a template to the given class.
<ItemsControl Name="icTodoList" ItemsSource="{Binding MyClass}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Image Source="{Binding Image)"
<TextBlock Text="{Binding Title}"
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

Changing content according to selected option in WPF

I'm interested in creating an app that displays some buttons and changes a viewport according to the selected button. The viewport in my app is a ContentControl and I thought of changing its content whenever a button is clicked. However, I believe there's a better approach, by perhaps injecting the ViewModels of each of the Views I want to present to the ContentControl and styling them using DataTemplates (Since I want to avoid having a grid with many controls and just setting their Visibility property whenever I want to show a particular view). Which of the approaches seems better to you? Do you have a different approach for this?
The view should be something similar to this:
Thanks!
Usually have a ViewModel behind the window which contains:
ObservableCollection<IViewModel> AvailableViewModels
IViewModel SelectedViewModel
ICommand SetCurrentViewModelCommand
I display the AvailableViewModels using an ItemsControl, which has its ItemTemplate set to a Button. The Button.Command is bound to the SetCurrentViewModelCommand, and it passes the current data item from the AvailableViewModels collection in through the CommandParameter
To display the content area, I use a ContentControl with ContentControl.Content bound to SelectedViewModel, and DataTemplates get used to tell WPF how to render each ViewModel.
The end result is my XAML looks something like this:
<Window.Resources>
<DataTemplate DataType="{x:Type local:ViewModelA}">
<local:ViewA />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ViewModelB}">
<local:ViewB />
</DataTemplate>
</Window.Resources>
<DockPanel>
<Border DockPanel.Dock="Left" BorderBrush="Black" BorderThickness="0,0,1,0">
<ItemsControl ItemsSource="{Binding AvailableViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.SetCurrentViewModelCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding }"
Margin="2,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<ContentControl Content="{Binding SelectedViewModel}" />
</DockPanel>
You can view an example of the full code used for such a setup on my blog

Switch template based on parent property. Possible?

Here is my scenario. Working with Bing Map control(MVVM):
<m:Map x:Name="MainMap"
ZoomLevel="{Binding MapZoomLevel, Mode=TwoWay}"
Center="{Binding MapCenter, Mode=TwoWay}"
LogoVisibility="Collapsed"
CopyrightVisibility="Collapsed"
CredentialsProvider="{Binding BingApiKey}"
UseInertia="True"
Mode="Road" Grid.Column="2" Grid.RowSpan="5">
<m:MapItemsControl
ItemsSource="{Binding Source={StaticResource WorkLayerData}}">
<m:MapItemsControl.ItemTemplate>
<DataTemplate>
<Border m:MapLayer.Position="{Binding Location}"
Background="LightPink" BorderBrush="Black">
<TextBlock Text="{Binding DisplayId}" />
</Border>
</DataTemplate>
</m:MapItemsControl.ItemTemplate>
</m:MapItemsControl>
</m:Map>
On a bottom you see how I bind my "custom" pushpins by simply declaring DataTemplate with Border and TextBlock.
What I want is to declare 3 templates for the same item and choose them based on ZoomLevel property of MainMap
For example, when ZoomLevel<=3 I willdisplay small dots, when it is between 3 and 8 I will display more fancy pushpin with ID and when it's 8+ I may display even more info.
It's a simple idea but I'd like to know if possible..
Have a look at a DataTemplateSelector solution for Silverlight.

Categories

Resources