WPF Telerik Rad Map Polygon Data binding to Polygon Data within class - wpf

I am trying to add polygons to the telerik rad map with a PolygonData class embedded within a parent class.
public class PolygonClass
{
public int ID { get; set; }
public PolygonData Polygon { get; set; }
}
I'm trying to bind my VisualizationLayer.ItemSource to the 'Polygon' Property within 'PolygonClass' because I need to reference an ID value in various other places of my application. The only way I've recently been able to make this work is by binding to a property of ObservableCollection.
Has anyone else ran into this and knows of a solution? Thanks in advance.

There are several ways to achieve your requirement.
You can populate the Items collection of VisualizaztionLayer (instead of ItemsSource) with PolygonData objects. Any additional information, like the the ID, can be stored in the ExtendedData property of the PolygonData.
PolygonData polygon = new PolygonData();
polygon.ExtendedData["ID"] = 3;
Or you can use the map bindable wrappers inside the ItemTemplate property of VisualizationLayer. In your case the wrapper that should be used is MapPolygonView.
<telerik:VisualizationLayer.ItemTemplate>
<DataTemplate>
<telerik:MapPolygonView Points="{Binding Polygon.Points}" />
</DataTemplate>
</telerik:VisualizationLayer.ItemTemplate>
Note that in this case, you won't need the PolygonData in your PolygonClass, because the MapPolygonView will automatically generate one and add in the VisualizationLayer. Instead, you can define the shape information (like points and fill) in PolygonClass and data bind to those.

Related

Where can I use a DataTemplate in something that isn't a repeater type of control?

Ok, I know it's kind of weird, but I am trying to create a data driven panel that reconfigures itself based on a DataTemplate member that I have on a object. Right now I am accomplishing this by using an ItemsControl bound against a dummy list of 1 bogus item so that I get a single instance of the data template. It just seems silly to have to do this in an ItemsControl, but I can't think of anything that will use my DataTemplate without trying to do it against a list of items. Anyone have any idea?
Just for clarity, let's say I have a Widget class:
public class Widget
{
public string Name { get; set; }
public DataTemplate MyTemplate { get; set; }
public List<object> DummyList = new List<object> { new object(); }
}
and the Xaml something like:
<ItemsControl ItemsSource={Binding DummyList} ItemTemplate={Binding MyTemplate}/>
I can then create a collection of Widgets and populate each one with the correct data template based on the object's status.
Anyway, as I said, this works... I'd just like to find a more elegant solution than using an ItemsControl if anyone knows of one.
Chances are that you could also just set ContentTemplate="{Binding template}" if your control (that you wish to dynamically modify its contents - e.g. Button inside etc.) is ContentControl. I found that often 'overlooked' as it's not immediately visible or intuitive, but saves you adding extra 'content'.
Or you can use ContentControl - or presenter as suggested already.
<ContentPresenter ContentTemplate="{Binding MyTemplate}"/>

Binding to a property of the DataContext of another control

iv'e got 2 panels in an app game
they are both bound to different elements .
GameDetailsPanel.DataContext = game ;
GameBoardPanel.DataContext = gameBoard ;
*Game has a Turn Property * .
public Class Game
{
public bool Turn{ get; set;}
}
now i need to bind one of GameBoardPanel to the value of the Property Turn ,
*for example : something along the lines of *
<Button Fill={Binding Source=GameDetailsPanel.DataContext , Path=Turn } ></Button>
how can i reference GameDetailsPanel.DataContext in my binding ?
For the benefit of searchers, you can bind to the datacontext of another control as detailed here.
The quick solution in my case looked like:
<TextBlock Text="{Binding ElementName=ucClientDetails,
Path=DataContext.FullName}"></TextBlock>
where 'ucClientDetails' was a user control bound to a viewmodel containing client details (including FullName).
I would recommend having your game and gameBoard properties on a wrapper view model and then setting the datacontext of your view to the wrapper view model. That way in your button's Fill binding you could simply reference the appropriate property on your view model:
public Class Wrapper_ViewModel
{
public Game game{ get; set; }
public T gameBoard{ get; set; }
}
<Button Fill={Binding Path=game.Turn} ></Button>
However, for more one-off scenarios you could use the relative source binding attribute and hook another elements data context, as in this example:
Access parent DataContext from DataTemplate
use simply
<Button Fill="{Binding ElementName=GameDetailsPanel,Path=DataContext.Turn}"></Button>
this element binding.

What approach should I use when creating a custom WPF control?

I'm about to redo an old WinForms application as a WPF application. The core of this applicaton is a custom "grid" component. I'd like some ideas on the best way to do this as a WPF component.
The application displays a grid of data for different countries/sectors. Each cell of the grid displays different information (e.g. graph, image) depending on the available data for that country/sector.
I have a domain model assembly that I want to keep clean - to maximize reuse. The structure is as follows:
Table
Continents
Countries
Sectors
Data[country, sector]
The grid displays countries down the left and sectors across the top.
In the current application, the grid component has a (POCO) Table property and an Refresh() methods to manually redraw it. So, if the Table is updated, the parent of the grid component refreshes it. The grid component also has a number of events that are fired if a continent, country or cell is clicked - so that the parent can response with pop-up menus, etc.
This all works fine.
However, I'm wondering whether this is the correct model to use for a WPF application. Looking at many of the WPF example, they support data-binding, etc. But, it's not clear, from the simple examples, how I might bind a complex object to my components - or whether it would even be worthwhile.
Also, the WinForms component is completely custom drawn - there are no sub-controls (e.g. Labels) in use. Would it be better to use a WPF user control and build the table from a GridLayout and lots of Label, Shape, etc controls? In practice, they are maybe 20 rows and 20 columns in the grid, and the user regular removes and adds countries/sectors (rows/columnms) while using the application.
My immediate goal is to make sure my design plays well in the WPF eco-system, but I have a secondary goal of learning how to do things in a WPFy way - given this is my first WPF app. I'm pretty on top of the use of building a general WPF app - it's just the custom control stuff that remains a little fuzzy (even after reading around it a little).
Any insights/guidance would be appreciated.
You definitely want to adapt the MVVM approach, as outlined by Josh Smith. Practically, this means that your custom grid component will be contained in it's own View. Backing the view will be your ViewModel, where you will define an ObservableCollection of objects containing your data. These objects will probably come from your Model. This interaction is shown below:
Models:
public class TableData
{
public string Country { get; set; }
public string Continent { get; set; }
public object Sector { get; set; }
}
public class TableManager : ITableManager
{
public Collection<TableData> Rows;
public void GetData()
{
this.Rows = new Collection<TableData>();
this.Rows.Add(...
}
}
ViewModel:
public class TableViewModel
{
private ITableManager _tableManager;
public TableViewModel() : base(new TableManager())
{
}
// for dependency injection (recommended)
public TableViewModel(ITableManager tableManager)
{
_tableManager = tableManager;
_tableManager.GetData();
}
public ObservableCollection<TableData> Rows
{
get { return _tableManager.Rows; }
}
}
View:
<ctrls:CustomDataGrid
ItemsSource={Binding Rows}
AutoGenerateColumns=True
>
<!-- Use AutoGenerateColumns if the # of sectors is dynamic -->
<!-- Otherwise, define columns manually, like so: -->
<DataGridTextColumn
Width="*"
Header="SectorA"
Binding="{Binding Country}
/>
</ctrls:CustomDataGrid>
I used CustomDataGrid in the view because I assume you're going to subclass your own DataGrid. This will allow you to override events to customize the DataGrid to your liking:
public class CustomDataGrid : DataGrid
{
public override Event...
}

Silverlight: how to bind List<T> to data grid

MVVM pattern is implemented in my Silverlight4 application.
Originally, I worked with ObservableCollection of objects in my ViewModel:
public class SquadViewModel : ViewModelBase<ISquadModel>
{
public SquadViewModel(...) : base(...)
{
SquadPlayers = new ObservableCollection<SquadPlayerViewModel>();
...
_model.DataReceivedEvent += _model_DataReceivedEvent;
_model.RequestData(...);
}
private void _model_DataReceivedEvent(ObservableCollection<TeamPlayerData> allReadyPlayers, ...)
{
foreach (TeamPlayerData tpd in allReadyPlayers)
{
SquadPlayerViewModel sp = new SquadPlayerViewModel(...);
SquadPlayers.Add(sp);
}
}
...
}
Here is a peacie of XAML code for grid displaying:
xmlns:DataControls="clr-namespace:System.Windows.Controls;
assembly=System.Windows.Controls.Data"
...
<DataControls:DataGrid ItemsSource="{Binding SquadPlayers}">
...</DataControls:DataGrid>
and my ViewModel is bound to DataContext property of the view.
This collection (SquadPlayers) is not changed after its creation so I would like to change its type to
List<SquadPlayerViewModel>
. When I did that, I also added
RaisePropertyChanged("SquadPlayers")
in the end of '_model_DataReceivedEvent' method (to notify the grid that list data are changed.
The problem is that on initial displaying grid doesn't show any record... Only when I click on any column header it will do 'sorting' and display all items from the list...
Question1: Why datagrid doesn't contain items initially?
Q2: How to make them displayed automatically?
Thanks.
P.S. Here is a declaration of the new List object in my view-model:
public List<SquadPlayerViewModel> SquadPlayers { get; set; }
You can't use List as a binding source, because List not implement INotifyCollectionChanged it is require for WPF/Silverlight to have knowledge for whether the content of collection is change or not. WPF/Sivlerlight than can take further action.
I don't know why you need List<> on your view model, but If for abstraction reason you can use IList<> instead. but make sure you put instance of ObservableCollection<> on it, not the List<>. No matter what Type you used in your ViewModel Binding Only care about runtime type.
so your code should like this:
//Your declaration
public IList<SquadPlayerViewModel> SquadPlayers { get; set; }
//in your implementation for WPF/Silverlight you should do
SquadPlayers = new ObservableCollection<SquadPlayerViewModel>();
//but for other reason (for non WPF binding) you can do
SquadPlayers = new List<SquadPlayerViewModel>();
I usually used this approach to abstract my "Proxied" Domain Model that returned by NHibernate.
You'll need to have your SquadPlayers List defined something like this:
private ObservableCollection<SquadPlayerViewModel> _SquadPlayers;
public ObservableCollection<SquadPlayerViewModel> SquadPlayers
{
get
{
return _SquadPlayers;
}
set
{
if (_SquadPlayers== value)
{
return;
}
_SquadPlayers= value;
// Update bindings, no broadcast
RaisePropertyChanged("SquadPlayers");
}
}
The problem is that whilst the PropertyChanged event informs the binding of a "change" the value hasn't actually changed, the collection object is still the same object. Some controls save themselves some percieved unnecessary work if they believe the value hasn't really changed.
Try creating a new instance of the ObservableCollection and assigning to the property. In that case the currently assigned object will differ from the new one you create when data is available.

Bind a WPF data grid to multiple data sources

I have created a data grid in WPF and have 2 lists. I want to bind one column to one list and rest of the columns to another list.
Can anyone please tell me how to do this?
Thanks
Basically, You cant. The datagrid is an ItemsControl which has one ItemsSource property.
What i would do is build a view model which is a composite object that contains one of each of the items (from the two lists). then you could bind to a collection of these.
public class CompositeItem{
public Object ItemFromListOne { get; set; }
public Object ItemFromListTwo { get; set; }
}

Resources