I\'m fairly new to WPF and looking for a simple solution to the problem described below. I\'ve tried to make this as short as possible.
I\'m trying to visualize a \"
DataBinding is the way to go. Read here, http://msdn.microsoft.com/en-us/magazine/dd419663.aspx.
Once you've set up a viewmodel and set the datacontext of the view.
I suggest putting your elements in an observablecollection and bind it to an itemscontrol in the canvas.
For the elements to be positioned, you must create a custom ItemTemplate for the ItemsControl which uses a canvas, rather than the default stackpanel as container.
Then you can go ahead and create datatemplate for the various types of elements you have to get a specific look and feel pr element type.
This is a rough outline of a solution, hope this helps.
Example:
<Window x:Class="WorldCanvas.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WorldCanvas"
Title="WorldCanvas" Height="500" Width="500"
>
<Window.Resources>
<DataTemplate DataType="{x:Type local:HouseVM}" >
<Canvas>
<Rectangle Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}" Width="13" Height="23" Fill="Brown" />
</Canvas>
</DataTemplate>
<DataTemplate DataType="{x:Type local:BallVM}">
<Canvas>
<Ellipse Canvas.Left="{Binding X}" Canvas.Top="{Binding Y}" Width="13" Height="13" Fill="Blue" />
</Canvas>
</DataTemplate>
</Window.Resources>
<Grid>
<Canvas x:Name="TheWorld" Background="DarkGreen">
<Button Content="MoveFirst" Click="Button_Click" />
<ItemsControl ItemsSource="{Binding Entities}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding X}" />
<Setter Property="Canvas.Top" Value="{Binding Y}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Canvas>
</Grid>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
var worldViewModel = new WorldViewModel();
DataContext = worldViewModel;
}
void Button_Click(object sender, RoutedEventArgs e)
{
var viewModel = DataContext as WorldViewModel;
if(viewModel != null)
{
var entity = viewModel.Entities.First();
entity.X +=10;
}
}
}
Viewmodels
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if(PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class WorldViewModel : ViewModelBase
{
ObservableCollection<EntityVM> entities;
public ObservableCollection<EntityVM> Entities {
get { return entities; }
set
{
entities = value;
NotifyPropertyChanged("Entities");
}
}
public WorldViewModel()
{
Entities = new ObservableCollection<EntityVM>();
int y=0;
for(int i=0; i<30; i++)
{
if(i %2 == 0)
{
Entities.Add(new BallVM(i*10, y+=20));
}
else
{
Entities.Add(new HouseVM(i*20, y+=20));
}
}
}
}
public class EntityVM : ViewModelBase
{
public EntityVM(double x, double y)
{
X = x;
Y = y;
}
private double _x;
public double X
{
get
{
return _x;
}
set
{
_x = value;
NotifyPropertyChanged("X");
}
}
private double _y;
public double Y
{
get
{
return _y;
}
set
{
_y = value;
NotifyPropertyChanged("Y");
}
}
}
public class BallVM : EntityVM
{
public BallVM(double x, double y) : base(x, y)
{
}
}
public class HouseVM : EntityVM
{
public HouseVM(double x, double y) : base(x, y)
{
}
}