代码结构
MainWindow.xaml
<Window x:Class="MVVM_Simple_Exercise.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MVVM_Simple_Exercise"
Title="Car Management Window" Height="400" Width="600">
<Grid>
<ItemsControl ItemsSource="{Binding Cars}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Canvas.Left" Value="{Binding Left}" />
<Setter Property="Canvas.Top" Value="{Binding Top}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--<Ellipse Width="50" Height="50" Fill="Red"
Canvas.Left="{Binding Left}" Canvas.Top="{Binding Top}"/>-->
<Ellipse Width="50" Height="50" Fill="Red"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
using MVVM_Simple_Exercise.ViewModels;
namespace MVVM_Simple_Exercise
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
CarViewModel viewModel = new CarViewModel();
this.DataContext = viewModel;
}
}
}
DelegateCommand.cs
using System;
using System.Windows.Input;
namespace MVVM_Simple_Exercise.Commands
{
class DelegateCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
if (CanExecuteFunc == null)
{
return true;
}
return this.CanExecuteFunc(parameter);
}
public void Execute(object parameter)
{
if (ExecuteAction == null)
{
return;
}
this.ExecuteAction(parameter);
}
public Func<object,bool> CanExecuteFunc { get; set; }
public Action<object> ExecuteAction { get; set; }
}
}
CarModel.cs
using MVVM_Simple_Exercise.ViewModels;
namespace MVVM_Simple_Exercise.Models
{
public class CarModel : NotificationObject
{
private double left;
public double Left
{
get { return left; }
set
{
//if (left != value)
//{
left = value;
RaisePropertyChanged();
//}
}
}
private double top;
public double Top
{
get { return top; }
set
{
//if (top != value)
//{
top = value;
RaisePropertyChanged();
//}
}
}
public void Move(double deltaX, double deltaY)
{
Left += deltaX;
Top += deltaY;
}
}
}
CarViewModel.cs
using MVVM_Simple_Exercise.Models;
using System.Collections.ObjectModel;
using System.Timers;
using System.Windows;
namespace MVVM_Simple_Exercise.ViewModels
{
public class CarViewModel : NotificationObject
{
private Timer timerCreate;
private Timer timerMove;
public ObservableCollection<CarModel> Cars { get; } = new ObservableCollection<CarModel>();
public CarViewModel()
{
timerCreate = new Timer(5000); // 每秒执行一次
timerCreate.Elapsed += Timer_Elapsed;
timerCreate.Start();
timerMove = new Timer(1000); // 每秒执行一次
timerMove.Elapsed += Timer_ElapsedMove;
timerMove.Start();
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
// 在定时器触发时创建新的小车对象
Application.Current.Dispatcher.Invoke(() =>
{
var car = new CarModel();
Cars.Add(car);
});
}
private void Timer_ElapsedMove(object sender, ElapsedEventArgs e)
{
// 更新所有小车的位置
foreach (var car in Cars)
{
car.Move(100, 0); // 每次移动10个像素
}
}
}
}
NotificationObject.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MVVM_Simple_Exercise.ViewModels
{
public class NotificationObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName()] string propertyName = null/*告诉binding到底是那个属性它的值发生改变了*/)
{
if (propertyName != null) PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); // binding关注的的确是这个property,赶紧将这个值传到界面上去
}
}
}