I have the requirement in my WP7 application to display pushpins on a bing map from multiple data sources and I am not sure of the best way to do this.
So for example it would be something like this, I receive from a web service a list of people, a list of buildings, a list of POIs etc. I would need to display these individually in their own views but also display them on a map with different images for each type.
I am trying to use a MVVM approach so have a class for a Person, class for a building and so on, each one of these has a location. I then have an ObservableCollection for each of these types and so using data binding it is easy enough to do a View for each of these.
At the moment I only have one ViewModel but my first thought is that I think I should really have one ViewModel per type. So PersonViewModel, BuildingViewModel here? However a Map View would then need to take information from each of these views and I am no sure how you bind a view to multiple ViewModels like this or even if that is sensible.
MapItemsControl also only seems to be able to bind to one thing so how can I bind it to multiple different data sources like this? I thought I could create a simple pushpin class but that would then mean having the data for each type duplicated and I eventually want to be able to click on the pushpins to display the details for the pin so wanted to keep the types separate
Any pointers on a way forward much appreciated
Using a MapItemsControl is as you say, the way to do it. And it's very easy. What you want is a ViewModel with a ObservableCollection for each of your types, as you say you already have.
So I guess your problem is that you don't understand how to use Styles and ItemTemplates.
If what you want, is to have the same style for each of the different types, then simply define a common ItemTemplate that you apply to each MapItemsControl.ItemTemplate. Likewise you can define a custom style that you apply to each Pushpin globally, if what's what you want.
<Grid.Resources>
<DataTemplate x:Name="PushpinItemTemplate">
<maps:Pushpin Location="{Binding Location}" Tap="Pushpin_Tap" Style="{StaticResource PushpinStyle}" />
</DataTemplate>
</Grid.Resources>
...
<maps:Map>
<maps:MapLayer>
<maps:MapItemsControl ItemsSource="{Binding People}" ItemTemplate="{StaticResource PushpinItemTemplate}" />
<maps:MapItemsControl ItemsSource="{Binding Buildings}" ItemTemplate="{StaticResource PushpinItemTemplate}" />
</maps:MapLayer>
</maps:Map>
Related
I am new to MVMM Light toolkit (note, I'm using Light on .NET 3.5). So far I am really starting to like the pattern save for two challenges.
I'd like to have reusable XAML templates for certain types of pages in my application. Think of a movie ticket kiosk. Main content in the center but almost always a button somewhere on the screen to cancel or go back. I'd like to have reusable grid(s) where when I create a new page I basically import that grid layout and don't have to worry about the common bits and can just focus on my part. Doing a little research I feel like <ContentPresenter> might be the way to go here but it's still foreign to me.
Assumign I succeed in my first challenge, I would think the data context for those common items (say a Cancel button) would be somewhere else other than that page's ViewModel to avoid a bunch of duplication of code. Is that best approach to take the individual controls and reference a different view model from the XAML? Something like...
<Button ... DataContext={Binding CommonStuffVM, Source={StaticResource Locator}} />
You can use Templates or DataTemplates to create a reusable template defining how an object should look.
For example,
<DataTemplate DataType="{x:Type local:MovieTicket}">
<!-- Write the XAML for your Movie Ticket -->
</DataTemplate>
You can give your DataTemplate an x:Key to reference it specifically in an ItemTemplate or ContentTemplate, or leave it out so it will be used anytime WPF tries to draw a MovieTicket object
<ItemsControl ItemsSource="{Binding MovieTickets}" />
<ContentControl Content="{Binding SelectedMovieTicket}" />
For your second question, I think this would be a bad idea for individual controls, although its a common practice for complete sections of the program.
When using MVVM, your ViewModels are your application, not your UI.
If your window should display a list of Movies for the user to edit, and allow the user to Save or Cancel their changes, then your ViewModel should contain an ObservableCollection<Movie> and contain an ICommand SaveCommand and ICommand CancelCommand
You really want your View to only reflect your ViewModels, and not have them pulling the data they need from all over the ViewModel hierarchy.
Based on your question, you may be interested in a blog article I have about Navigation with MVVM which uses code very similar to what you're asking about. It shows how to change the UI using implicit DataTemplates, and contains a complete code sample that you can download and look at to get a better idea of the MVVM architecture.
Is it possible to store some data in every item of a TreeView control? I mean, something useful (e.g. a string) besides the header text?
Thanks.
Yes, WPF is "lookless", so your actual data can be anything you want it to be, and a TreeView is just a Template used to display the data to the user in a pre-determined way.
You can overwrite any part of that Template to be whatever you want, and/or have it bind to your data however you want.
Edit
I'm no expert on using the TreeView, but if you had a DataContext of List<Folder>, and each Folder object had a Name and a FullPath property, your TreeView could look something like this:
<TreeView ItemsSource="{Binding MyFolderList}">
<TreeView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"
ToolTip="{Binding FullPath}" />
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
If you haven't already, I'd highly recommend looking into the MVVM design pattern when working with WPF. Basically your application is your classes (ViewModels), and the Controls/XAML (Views) are just a pretty layer that sits on top of your classes to make them user-friendly.
This is an important concept when switching from a WinForms TreeView to a WPF TreeView
It depends on what you mean by store data...
If you're just talking UI customization Rachel's answer above works.
If you're talking about storing arbitrary object values, such as information about the TreeViewItem, or maybe a relation between two items, you can use the Tag property of TreeViewItem. For example, I had to write a mapping UI where two trees linked together where each TreeViewItem from the first tree, could connect to 1 TreeViewItems of the second tree. I used the Tag property of the first TreeViewItem to store the connecting TreeViewItem.
I have a collection of objects that I want to present. How can I do this? A listbox would do but each object has many attributes which I want to present. I already bound a listbox to a collection and I have all my objects listed. My question is regarding the visualization of the listbox and if the listbox is the correct thing to use or there is something else that I should use.
I find the existing answers to be a bit lacking, normally one would not process collections or boil their items down to a string, at the very best you would do some dynamic manipulation using a CollectionView (e.g. sorting, grouping), but normally you use Data Templating to display the individual items which allows you to use all their properties.
Further there are several controls which work well with collections, firstly you need to know if you want selection, if not an ItemsControl is a good choice, otherwise you should use a ListBox or ListView.
ListViews are normally employed if you have different views for your objects, e.g. a details view and a thumbnail view. You can use the ListView.View for this, there is one existing view in the framework, the GridView, which offers columns. What Matthew Ferreira suggested is exactly what you should not do with a ListView since you want to make the templates dependent on the current view, in fact that code does not even compile since DataTemplate can only have one child.
ListViews are supposed to encapsulate the view logic in their view so it can be changed at will. If you decide to use a ItemsControl or ListBox then setting the ItemTemplate is what you want to do. Read the Data Templating overview i linked to, it makes for a good starting point.
You might want to consider using a ListView control instead. ListView has support for columns if you are planning on showing several properties from your object. You can use the ItemTemplate property to format the display of your object. For example:
<ListView ItemsSource="{Binding Path=myObjectCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Title}"/>
<CheckBox IsChecked="{Binding Path=ShouldCheck}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This example assumes that your object has the properties Title and ShouldCheck.
Your collection of object is probably to be viewed as your model. The usual thing in WPF is to add a ViewModel that translates and exposes the model data into a form suitable for binding. Depending on what you want to do, your VM could e.g. format each object into a string representation and then expose it as a collection of strings that the Listbox can bind to and display.
I was looking for best approach to set data context property. I found three ways
Assign data context on View (either on XAML or code behind).
Assign data context on ViewModel through constructor.
Use some configuration that takes view and view model reference and bind data context on run time through some infrastructure classes.
Which is the best option among this in terms of loosely coupled, maintainable? Or Is there any best approach?
I personally like this approach because it makes me have to write less code :). It basically uses an IValueConverter to lookup which view to use whenever a wpf control needs to present a ViewModel visually and the IValueConverter sets the datacontext for you. It also shows you how to create a datatemplate that allows you to require WPF to utilize this converter by default, something like this:
<DataTemplate DataType="{x:Type ViewModels:ViewModelBase}">
<ContentControl Content="{Binding Converter={StaticResource MyConverter}}"/>
</DataTemplate>
the 4. way would be a DataTemplate.
i think the best approach is the one which fits best in your current situation.
if i have viewmodel first dynamic scenarios i use datatemplate/contentpresenter or with view first i take your way one and so on...
I'm brand spanking new to WPF and am trying to play around with projects to better understand what I'm reading.
My understanding of a resource is that it is the instance, you can't use it like a factory and create instances of it. For example, a XAML-defined rectangle. You can reference it, but you can't have numerous instances of it all over the surface.
In WPF, what would be the way to do that? If I define a Rectangle as a resource with specific properties and wanted to have multiple instances of that within a dynamically-generated grid, how should I be going about it? Or is there a different way I should be trying to do this?
Purely academic exercise with no real-world application.
Actually there's nothing about resources in particular that prevents you from using it multiple times. A perfect example of this is brush resources, style resources, etc. You define them in XAML and the XAML parser creates a single instance of the resources and stores them in the resource dictionary and these brushes, styles, etc can be used as property values many times even though only a single instance of the resource was created.
But having said that, as you noted, you can't really define a Rectangle resource and use it multiple times in the visual tree. This has nothing to do with the fact that it's a resource, but rather it has to do with the fact that a FrameworkElement cannot be a child of more than one parent element.
So what we have instead is called "templates". These tell WPF how to create an element tree but does not actually create the tree until you instantiate the template. Below is an example.
<UserControl>
<ItemsControl ItemsSource="{Binding WholeBunchOfItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Rectangle Fill="Yellow" />
<ContentPresenter Content="{Binding}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</UserControl>
In this example I've bound an ItemsControl to a collection of some sort. For each item in the collection, the ItemsControl will use my DataTemplate to render the item. Within a DataTemplate you can use data binding to access the current item.
I would suggest reading up on MSDN about ControlTemplate, DataTemplate, and Style. These are all important concepts in WPF/Silverlight.
To get multiple instances replicated across a grid or listbox, you need to set the data template to define the UI controls for each row of data, and then databind the grid or listbox to a collection of data that determines how many rows and the individual field values.
Key term for you to research first: data template.