How to use WPF to visualize a simple 2D world (map and elements)

前端 未结 1 1865
难免孤独
难免孤独 2020-12-21 08:25

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 \"

相关标签:
1条回答
  • 2020-12-21 09:22

    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)
        {
        }
    }
    
    0 讨论(0)
提交回复
热议问题