WPF实现电梯算法动态演示应用

一、项目概述

本应用旨在通过WPF实现电梯调度算法的动态可视化演示,帮助用户直观理解不同电梯调度算法的工作原理和性能差异。

二、项目结构

ElevatorSimulation/
├── ElevatorSimulation/          # 主程序
│   ├── Models/                  # 数据模型
│   ├── Views/                   # 视图层
│   ├── ViewModels/              # 视图模型
│   ├── Algorithms/              # 算法实现
│   └── Resources/               # 资源文件
└── ElevatorSimulation.sln       # 解决方案文件

三、核心功能实现

1. 数据模型 (Models/ElevatorModel.cs)

public class ElevatorModel
{
    public int CurrentFloor { get; set; } = 1;
    public Direction CurrentDirection { get; set; } = Direction.Idle;
    public List<int> RequestedFloors { get; } = new List<int>();
    public bool IsMoving { get; set; } = false;
    
    public enum Direction
    {
        Up,
        Down,
        Idle
    }
}

public class FloorRequest
{
    public int FloorNumber { get; set; }
    public DateTime RequestTime { get; set; }
    public bool IsCompleted { get; set; } = false;
}

2. 视图模型 (ViewModels/MainViewModel.cs)


public class MainViewModel : INotifyPropertyChanged
{
    private ElevatorModel _elevator;
    private List<FloorRequest> _requests;
    private ElevatorAlgorithm _currentAlgorithm;
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    public ElevatorModel Elevator
    {
        get => _elevator;
        set
        {
            _elevator = value;
            OnPropertyChanged();
        }
    }
    
    public List<FloorRequest> Requests
    {
        get => _requests;
        set
        {
            _requests = value;
            OnPropertyChanged();
        }
    }
    
    public ElevatorAlgorithm CurrentAlgorithm
    {
        get => _currentAlgorithm;
        set
        {
            _currentAlgorithm = value;
            OnPropertyChanged();
        }
    }
    
    public ICommand StartSimulationCommand { get; }
    public ICommand AddRequestCommand { get; }
    public ICommand ResetSimulationCommand { get; }
    
    public MainViewModel()
    {
        Elevator = new ElevatorModel();
        Requests = new List<FloorRequest>();
        CurrentAlgorithm = ElevatorAlgorithm.FCFS;
        
        StartSimulationCommand = new RelayCommand(StartSimulation);
        AddRequestCommand = new RelayCommand(AddRequest);
        ResetSimulationCommand = new RelayCommand(ResetSimulation);
    }
    
    private void StartSimulation()
    {
        // 启动电梯模拟线程
        Task.Run(() => SimulateElevator());
    }
    
    private void SimulateElevator()
    {
        while (Requests.Any(r => !r.IsCompleted))
        {
            // 根据当前算法选择下一个目标楼层
            int nextFloor = CurrentAlgorithm.SelectNextFloor(Elevator, Requests);
            
            if (nextFloor != Elevator.CurrentFloor)
            {
                Elevator.IsMoving = true;
                
                // 移动电梯
                if (nextFloor > Elevator.CurrentFloor)
                {
                    Elevator.CurrentDirection = ElevatorModel.Direction.Up;
                    for (int i = Elevator.CurrentFloor + 1; i <= nextFloor; i++)
                    {
                        Elevator.CurrentFloor = i;
                        UpdateRequests();
                        Thread.Sleep(500); // 模拟移动时间
                    }
                }
                else if (nextFloor < Elevator.CurrentFloor)
                {
                    Elevator.CurrentDirection = ElevatorModel.Direction.Down;
                    for (int i = Elevator.CurrentFloor - 1; i >= nextFloor; i--)
                    {
                        Elevator.CurrentFloor = i;
                        UpdateRequests();
                        Thread.Sleep(500);
                    }
                }
                
                Elevator.IsMoving = false;
            }
            
            // 处理到达楼层的请求
            ProcessRequestsAtCurrentFloor();
        }
        
        Elevator.CurrentDirection = ElevatorModel.Direction.Idle;
    }
    
    private void ProcessRequestsAtCurrentFloor()
    {
        var requestsAtFloor = Requests.Where(r => r.FloorNumber == Elevator.CurrentFloor && !r.IsCompleted).ToList();
        
        foreach (var request in requestsAtFloor)
        {
            request.IsCompleted = true;
            // 这里可以添加乘客进出电梯的逻辑
        }
    }
    
    private void UpdateRequests()
    {
        // 更新UI中的请求状态
        // 可以通过事件或INotifyPropertyChanged通知视图更新
    }
    
    private void AddRequest()
    {
        // 添加新的楼层请求
        var newRequest = new FloorRequest
        {
            FloorNumber = new Random().Next(1, 21), // 假设20层楼
            RequestTime = DateTime.Now
        };
        
        Requests.Add(newRequest);
    }
    
    private void ResetSimulation()
    {
        Elevator.CurrentFloor = 1;
        Elevator.CurrentDirection = ElevatorModel.Direction.Idle;
        Elevator.IsMoving = false;
        Requests.ForEach(r => r.IsCompleted = false);
    }
    
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

3. 算法实现 (Algorithms/ElevatorAlgorithm.cs)


public enum ElevatorAlgorithm
{
    FCFS,       // 先来先服务
    SSTF,       // 最短寻道时间优先
    SCAN,       // 电梯调度算法
    C_SCAN      // 循环电梯调度算法
}

public static class ElevatorAlgorithmExtensions
{
    public static int SelectNextFloor(this ElevatorAlgorithm algorithm, ElevatorModel elevator, List<FloorRequest> requests)
    {
        switch (algorithm)
        {
            case ElevatorAlgorithm.FCFS:
                return FCFS(elevator, requests);
            case ElevatorAlgorithm.SSTF:
                return SSTF(elevator, requests);
            case ElevatorAlgorithm.SCAN:
                return SCAN(elevator, requests);
            case ElevatorAlgorithm.C_SCAN:
                return C_SCAN(elevator, requests);
            default:
                return elevator.CurrentFloor;
        }
    }
    
    private static int FCFS(ElevatorModel elevator, List<FloorRequest> requests)
    {
        var pendingRequests = requests.Where(r => !r.IsCompleted).ToList();
        
        if (!pendingRequests.Any())
            return elevator.CurrentFloor;
            
        // 按请求时间排序
        var sortedRequests = pendingRequests.OrderBy(r => r.RequestTime).ToList();
        
        // 根据当前方向选择下一个请求
        if (elevator.CurrentDirection == ElevatorModel.Direction.Up)
        {
            var upRequests = sortedRequests.Where(r => r.FloorNumber >= elevator.CurrentFloor).ToList();
            if (upRequests.Any())
                return upRequests.First().FloorNumber;
            else
                return sortedRequests.Last().FloorNumber; // 没有上行请求,返回最下面的请求
        }
        else if (elevator.CurrentDirection == ElevatorModel.Direction.Down)
        {
            var downRequests = sortedRequests.Where(r => r.FloorNumber <= elevator.CurrentFloor).Reverse().ToList();
            if (downRequests.Any())
                return downRequests.First().FloorNumber;
            else
                return sortedRequests.First().FloorNumber; // 没有下行请求,返回最上面的请求
        }
        
        // 默认返回第一个请求
        return sortedRequests.First().FloorNumber;
    }
    
    private static int SSTF(ElevatorModel elevator, List<FloorRequest> requests)
    {
        var pendingRequests = requests.Where(r => !r.IsCompleted).ToList();
        
        if (!pendingRequests.Any())
            return elevator.CurrentFloor;
            
        // 计算每个请求与当前楼层的距离
        var distances = pendingRequests.Select(r => new
        {
            Request = r,
            Distance = Math.Abs(r.FloorNumber - elevator.CurrentFloor)
        }).ToList();
        
        // 根据方向优化选择
        if (elevator.CurrentDirection == ElevatorModel.Direction.Up)
        {
            var upRequests = distances.Where(d => d.Request.FloorNumber >= elevator.CurrentFloor)
                                     .OrderBy(d => d.Distance)
                                     .ThenBy(d => d.Request.FloorNumber)
                                     .ToList();
                                     
            if (upRequests.Any())
                return upRequests.First().Request.FloorNumber;
        }
        else if (elevator.CurrentDirection == ElevatorModel.Direction.Down)
        {
            var downRequests = distances.Where(d => d.Request.FloorNumber <= elevator.CurrentFloor)
                                       .OrderByDescending(d => d.Request.FloorNumber)
                                       .ThenBy(d => d.Distance)
                                       .ToList();
                                       
            if (downRequests.Any())
                return downRequests.First().Request.FloorNumber;
        }
        
        // 默认选择距离最近的请求
        return distances.OrderBy(d => d.Distance).First().Request.FloorNumber;
    }
    
    private static int SCAN(ElevatorModel elevator, List<FloorRequest> requests)
    {
        var pendingRequests = requests.Where(r => !r.IsCompleted).ToList();
        
        if (!pendingRequests.Any())
            return elevator.CurrentFloor;
            
        // 根据当前方向排序请求
        if (elevator.CurrentDirection == ElevatorModel.Direction.Up)
        {
            var upRequests = pendingRequests.Where(r => r.FloorNumber >= elevator.CurrentFloor)
                                           .OrderBy(r => r.FloorNumber)
                                           .ToList();
                                           
            if (upRequests.Any())
            {
                // 找到最远的上升请求
                var farthestUp = upRequests.Last();
                
                // 检查是否有下降请求在当前楼层和最远上升请求之间
                var downRequestsBetween = pendingRequests.Where(r => r.FloorNumber < farthestUp.FloorNumber && r.FloorNumber > elevator.CurrentFloor)
                                                         .OrderByDescending(r => r.FloorNumber)
                                                         .ToList();
                
                if (downRequestsBetween.Any())
                {
                    // 如果有,先处理最远的下降请求
                    return downRequestsBetween.First().FloorNumber;
                }
                
                return farthestUp.FloorNumber;
            }
        }
        else if (elevator.CurrentDirection == ElevatorModel.Direction.Down)
        {
            var downRequests = pendingRequests.Where(r => r.FloorNumber <= elevator.CurrentFloor)
                                              .OrderByDescending(r => r.FloorNumber)
                                              .ToList();
                                              
            if (downRequests.Any())
            {
                // 找到最远的下降请求
                var farthestDown = downRequests.First();
                
                // 检查是否有上升请求在当前楼层和最远下降请求之间
                var upRequestsBetween = pendingRequests.Where(r => r.FloorNumber > farthestDown.FloorNumber && r.FloorNumber < elevator.CurrentFloor)
                                                       .OrderBy(r => r.FloorNumber)
                                                       .ToList();
                
                if (upRequestsBetween.Any())
                {
                    // 如果有,先处理最远的上升请求
                    return upRequestsBetween.Last().FloorNumber;
                }
                
                return farthestDown.FloorNumber;
            }
        }
        
        // 默认行为 - 继续当前方向
        if (elevator.CurrentDirection == ElevatorModel.Direction.Up)
            return pendingRequests.Where(r => r.FloorNumber >= elevator.CurrentFloor)
                                 .OrderBy(r => r.FloorNumber)
                                 .FirstOrDefault()?.FloorNumber ?? elevator.CurrentFloor;
        else
            return pendingRequests.Where(r => r.FloorNumber <= elevator.CurrentFloor)
                                 .OrderByDescending(r => r.FloorNumber)
                                 .FirstOrDefault()?.FloorNumber ?? elevator.CurrentFloor;
    }
    
    private static int C_SCAN(ElevatorModel elevator, List<FloorRequest> requests)
    {
        var pendingRequests = requests.Where(r => !r.IsCompleted).ToList();
        
        if (!pendingRequests.Any())
            return elevator.CurrentFloor;
            
        if (elevator.CurrentDirection == ElevatorModel.Direction.Up)
        {
            // 处理所有上升请求
            var upRequests = pendingRequests.Where(r => r.FloorNumber >= elevator.CurrentFloor)
                                           .OrderBy(r => r.FloorNumber)
                                           .ToList();
                                           
            if (upRequests.Any())
            {
                // 找到最远的上升请求
                var farthestUp = upRequests.Last();
                
                // 如果没有更多上升请求,切换方向到最低楼层
                if (!pendingRequests.Any(r => r.FloorNumber < elevator.CurrentFloor))
                {
                    return farthestUp.FloorNumber;
                }
                
                return farthestUp.FloorNumber;
            }
        }
        else if (elevator.CurrentDirection == ElevatorModel.Direction.Down)
        {
            // 处理所有下降请求
            var downRequests = pendingRequests.Where(r => r.FloorNumber <= elevator.CurrentFloor)
                                              .OrderByDescending(r => r.FloorNumber)
                                              .ToList();
                                              
            if (downRequests.Any())
            {
                // 找到最远的下降请求
                var farthestDown = downRequests.First();
                
                // 如果没有更多下降请求,切换方向到最高楼层
                if (!pendingRequests.Any(r => r.FloorNumber > elevator.CurrentFloor))
                {
                    return farthestDown.FloorNumber;
                }
                
                return farthestDown.FloorNumber;
            }
        }
        
        // 默认行为 - 继续当前方向
        if (elevator.CurrentDirection == ElevatorModel.Direction.Up)
        {
            var upRequests = pendingRequests.Where(r => r.FloorNumber >= elevator.CurrentFloor)
                                           .OrderBy(r => r.FloorNumber)
                                           .ToList();
                                           
            if (upRequests.Any())
                return upRequests.Last().FloorNumber;
        }
        else
        {
            var downRequests = pendingRequests.Where(r => r.FloorNumber <= elevator.CurrentFloor)
                                              .OrderByDescending(r => r.FloorNumber)
                                              .ToList();
                                              
            if (downRequests.Any())
                return downRequests.First().FloorNumber;
        }
        
        return elevator.CurrentFloor;
    }
}

4. 视图实现 (Views/MainView.xaml)


<Window x:Class="ElevatorSimulation.Views.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ElevatorSimulation.Views"
        xmlns:vm="clr-namespace:ElevatorSimulation.ViewModels"
        mc:Ignorable="d"
        Title="电梯调度模拟器" Height="600" Width="800">
    <Window.DataContext>
        <vm:MainViewModel/>
    </Window.DataContext>
    
    <Grid>
        <!-- 电梯井道 -->
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="200"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        
        <!-- 控制面板 -->
        <StackPanel Grid.Column="0" Margin="10">
            <TextBlock Text="电梯控制面板" FontSize="16" FontWeight="Bold" Margin="0,0,0,10"/>
            
            <ComboBox ItemsSource="{Binding Source={StaticResource AlgorithmTypes}}" 
                      SelectedItem="{Binding CurrentAlgorithm}" 
                      DisplayMemberPath="Name" 
                      Margin="0,0,0,5"/>
            
            <Button Content="开始模拟" Command="{Binding StartSimulationCommand}" Margin="0,0,0,5"/>
            <Button Content="添加请求" Command="{Binding AddRequestCommand}" Margin="0,0,0,5"/>
            <Button Content="重置模拟" Command="{Binding ResetSimulationCommand}" Margin="0,0,0,20"/>
            
            <TextBlock Text="当前状态:" FontSize="14" FontWeight="Bold"/>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="楼层: " FontSize="12"/>
                <TextBlock Text="{Binding Elevator.CurrentFloor}" FontSize="12" Foreground="Blue"/>
                <TextBlock Text=" 方向: " FontSize="12"/>
                <TextBlock Text="{Binding Elevator.CurrentDirection, Converter={StaticResource DirectionConverter}}" FontSize="12" Foreground="Green"/>
            </StackPanel>
            
            <TextBlock Text="待处理请求:" FontSize="14" FontWeight="Bold" Margin="0,10,0,0"/>
            <ListBox ItemsSource="{Binding Requests}" Height="150">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal">
                            <TextBlock Text="{Binding FloorNumber}" Width="50"/>
                            <TextBlock Text="{Binding RequestTime, StringFormat='{}{0:HH:mm:ss}'}" Width="100"/>
                            <TextBlock Text="{Binding IsCompleted, Converter={StaticResource CompletionConverter}}" Foreground="{Binding IsCompleted, Converter={StaticResource CompletionColorConverter}}"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
        </StackPanel>
        
        <!-- 电梯井道可视化 -->
        <Grid Grid.Column="1" Margin="10">
            <Grid.RowDefinitions>
                <!-- 楼层显示区 -->
                <RowDefinition Height="Auto"/>
                <!-- 电梯井道 -->
                <RowDefinition Height="*"/>
                <!-- 控制按钮区 -->
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            
            <!-- 楼层标签 -->
            <ItemsControl ItemsSource="{Binding Floors}" Grid.Row="0">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Number}" 
                                   FontSize="14" 
                                   Margin="5"
                                   Foreground="{Binding IsCurrent, Converter={StaticResource CurrentFloorColorConverter}}"/>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
            
            <!-- 电梯井道 -->
            <Grid Grid.Row="1" Background="#EEE">
                <!-- 电梯轿厢 -->
                <Border x:Name="ElevatorCar" 
                        Width="80" 
                        Height="100" 
                        Background="#4CAF50" 
                        CornerRadius="5"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center">
                    <TextBlock Text="{Binding Elevator.CurrentFloor}" 
                               HorizontalAlignment="Center" 
                               VerticalAlignment="Center"
                               Foreground="White"
                               FontSize="16"/>
                </Border>
                
                <!-- 楼层分隔线 -->
                <ItemsControl ItemsSource="{Binding Floors}" Grid.Row="1">
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <Canvas/>
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <Line X1="0" Y1="{Binding YPosition}" 
                                  X2="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Canvas}}" 
                                  Y2="{Binding YPosition}" 
                                  Stroke="#CCC" StrokeThickness="1"/>
                            
                            <!-- 楼层按钮 -->
                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                                <Button Content="↑" Width="30" Height="30" Margin="0,0,5,0"
                                        Visibility="{Binding IsAboveCurrent, Converter={StaticResource VisibilityConverter}}"
                                        Command="{Binding Elevator.GoUpCommand, Source={StaticResource ElevatorViewModel}}"/>
                                <TextBlock Text="{Binding Number}" FontSize="12"/>
                                <Button Content="↓" Width="30" Height="30"
                                        Visibility="{Binding IsBelowCurrent, Converter={StaticResource VisibilityConverter}}"
                                        Command="{Binding Elevator.GoDownCommand, Source={StaticResource ElevatorViewModel}}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </Grid>
            
            <!-- 控制按钮区 -->
            <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
                <Button Content="1楼" Margin="5" Command="{Binding Elevator.GoToFloorCommand, Source={StaticResource ElevatorViewModel}, CommandParameter=1}"/>
                <Button Content="5楼" Margin="5" Command="{Binding Elevator.GoToFloorCommand, Source={StaticResource ElevatorViewModel}, CommandParameter=5}"/>
                <Button Content="10楼" Margin="5" Command="{Binding Elevator.GoToFloorCommand, Source={StaticResource ElevatorViewModel}, CommandParameter=10}"/>
                <Button Content="15楼" Margin="5" Command="{Binding Elevator.GoToFloorCommand, Source={StaticResource ElevatorViewModel}, CommandParameter=15}"/>
                <Button Content="20楼" Margin="5" Command="{Binding Elevator.GoToFloorCommand, Source={StaticResource ElevatorViewModel}, CommandParameter=20}"/>
            </StackPanel>
        </Grid>
    </Grid>
</Window>

5. 资源文件 (Resources/Converters.xaml)


<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:vm="clr-namespace:ElevatorSimulation.ViewModels">
    
    <!-- 算法类型集合 -->
    <ObjectDataProvider x:Key="AlgorithmTypes" MethodName="GetValues" ObjectType="{x:Type sys:Enum}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="vm:ElevatorAlgorithm"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
    
    <!-- 方向转换器 -->
    <local:DirectionConverter x:Key="DirectionConverter"/>
    
    <!-- 完成状态转换器 -->
    <local:CompletionConverter x:Key="CompletionConverter"/>
    <local:CompletionColorConverter x:Key="CompletionColorConverter"/>
    
    <!-- 楼层颜色转换器 -->
    <local:CurrentFloorColorConverter x:Key="CurrentFloorColorConverter"/>
    
    <!-- 可见性转换器 -->
    <BooleanToVisibilityConverter x:Key="VisibilityConverter"/>
</ResourceDictionary>

6. 算法可视化实现 (ViewModels/ElevatorViewModel.cs)


public class ElevatorViewModel : INotifyPropertyChanged
{
    private List<Floor> _floors;
    private ElevatorModel _elevator;
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    public List<Floor> Floors
    {
        get => _floors;
        set
        {
            _floors = value;
            OnPropertyChanged();
        }
    }
    
    public ElevatorModel Elevator
    {
        get => _elevator;
        set
        {
            _elevator = value;
            OnPropertyChanged();
        }
    }
    
    public ICommand GoToFloorCommand { get; }
    
    public ElevatorViewModel()
    {
        // 初始化电梯
        Elevator = new ElevatorModel();
        
        // 初始化楼层 (1-20层)
        Floors = Enumerable.Range(1, 20).Select(i => new Floor
        {
            Number = i,
            YPosition = (i - 1) * 50, // 每层50像素
            IsCurrent = i == Elevator.CurrentFloor,
            IsAboveCurrent = i > Elevator.CurrentFloor,
            IsBelowCurrent = i < Elevator.CurrentFloor
        }).ToList();
        
        // 命令绑定
        GoToFloorCommand = new RelayCommand<int>(GoToFloor);
    }
    
    private void GoToFloor(int floorNumber)
    {
        // 设置目标楼层
        var targetFloor = Floors.FirstOrDefault(f => f.Number == floorNumber);
        if (targetFloor != null)
        {
            // 更新电梯状态
            Elevator.CurrentFloor = floorNumber;
            
            // 更新楼层显示
            UpdateFloorDisplay();
        }
    }
    
    private void UpdateFloorDisplay()
    {
        foreach (var floor in Floors)
        {
            floor.IsCurrent = floor.Number == Elevator.CurrentFloor;
            floor.IsAboveCurrent = floor.Number > Elevator.CurrentFloor;
            floor.IsBelowCurrent = floor.Number < Elevator.CurrentFloor;
        }
        
        OnPropertyChanged(nameof(Floors));
    }
    
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Floor
{
    public int Number { get; set; }
    public double YPosition { get; set; }
    public bool IsCurrent { get; set; }
    public bool IsAboveCurrent { get; set; }
    public bool IsBelowCurrent { get; set; }
}

7. 转换器实现 (Converters/DirectionConverter.cs)


public class DirectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is ElevatorModel.Direction direction)
        {
            switch (direction)
            {
                case ElevatorModel.Direction.Up:
                    return "↑";
                case ElevatorModel.Direction.Down:
                    return "↓";
                default:
                    return "";
            }
        }
        return "";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

8. 主程序入口 (App.xaml.cs)


public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        
        // 初始化资源
        var resourceDictionary = new ResourceDictionary
        {
            Source = new Uri("Resources/Converters.xaml", UriKind.Relative)
        };
        
        // 合并资源字典
        Resources.MergedDictionaries.Add(resourceDictionary);
        
        // 启动主窗口
        var mainWindow = new Views.MainView();
        mainWindow.Show();
    }
}

三、功能扩展建议

  1. ​多电梯支持​​:扩展系统以支持多个电梯协同工作
  2. ​智能调度​​:实现更复杂的调度算法,如遗传算法优化
  3. ​能耗分析​​:添加电梯能耗计算和显示功能
  4. ​用户交互​​:允许用户通过界面按钮呼叫电梯
  5. ​性能监控​​:添加实时性能指标显示,如平均等待时间
  6. ​数据记录​​:记录模拟运行数据以便分析
  7. ​3D可视化​​:使用Helix Toolkit等库实现3D电梯井道可视化

四、技术要点总结

  1. ​MVVM模式​​:采用Model-View-ViewModel架构分离业务逻辑和界面
  2. ​数据绑定​​:利用WPF强大的数据绑定机制实现界面动态更新
  3. ​命令绑定​​:使用ICommand接口实现界面交互逻辑
  4. ​转换器​​:自定义IValueConverter实现数据格式转换
  5. ​资源管理​​:集中管理样式、模板和转换器等资源
  6. ​动画效果​​:可添加电梯移动动画增强用户体验

这个实现提供了一个完整的电梯调度模拟器框架,可以根据需要进一步扩展和完善功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

code_shenbing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值