You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI Ping应用单按钮实现启停功能故障求助

.NET MAUI Ping应用:实现按钮启停切换功能

核心问题分析

原代码存在以下关键问题导致启停功能失效:

  • 按钮同时绑定Command和Clicked事件,逻辑冲突
  • flag字段未实现属性通知,状态变化无法同步到UI和命令逻辑
  • Startc方法用Task.Delay().Wait()阻塞UI线程
  • 循环复用同一个PingData对象,导致列表数据引用冲突
  • 未实现停止逻辑,按钮文本无法随状态切换

解决方案与修改代码

步骤1:重构PingViewModel,实现状态管理与异步安全

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using System.Net.NetworkInformation;

namespace YourNamespace.ViewModels
{
    public class PingViewModel : INotifyPropertyChanged
    {
        private string _ip;
        private bool _isRunning;
        private string _buttonText = "Start";
        private CancellationTokenSource _cts; // 用于安全取消异步任务

        public ObservableCollection<PingData> PingCollection { get; set; }
        public ICommand TogglePingCommand { get; }

        public string Ip
        {
            get => _ip;
            set
            {
                _ip = value;
                OnPropertyChanged();
            }
        }

        public bool IsRunning
        {
            get => _isRunning;
            set
            {
                _isRunning = value;
                ButtonText = value ? "Stop" : "Start";
                OnPropertyChanged();
            }
        }

        public string ButtonText
        {
            get => _buttonText;
            set
            {
                _buttonText = value;
                OnPropertyChanged();
            }
        }

        public PingViewModel()
        {
            PingCollection = new ObservableCollection<PingData>();
            TogglePingCommand = new Command(ExecuteTogglePing);
        }

        private async void ExecuteTogglePing()
        {
            if (IsRunning)
            {
                // 停止Ping任务
                _cts?.Cancel();
                IsRunning = false;
            }
            else
            {
                if (string.IsNullOrWhiteSpace(Ip)) return; // 校验IP输入
                IsRunning = true;
                _cts = new CancellationTokenSource();
                await StartPingAsync(_cts.Token);
            }
        }

        private async Task StartPingAsync(CancellationToken token)
        {
            var pingOptions = new PingOptions { Ttl = 200 };

            while (!token.IsCancellationRequested)
            {
                var pingData = new PingData(); // 每次循环创建新实例,避免数据覆盖
                using (var ping = new Ping())
                {
                    try
                    {
                        var reply = await ping.SendPingAsync(Ip, 1000, null, pingOptions);
                        pingData.Status_ip = reply.Status.ToString();
                        pingData.IPAddress = reply.Address?.ToString() ?? Ip;

                        if (reply.Status == IPStatus.Success)
                        {
                            pingData.TTL = reply.Options.Ttl.ToString();
                            pingData.ResponseTime = reply.RoundtripTime.ToString();
                        }
                    }
                    catch (PingException ex)
                    {
                        pingData.Status_ip = $"Error: {ex.Message}";
                    }
                }

                PingCollection.Insert(0, pingData);
                await Task.Delay(1000, token); // 非阻塞延迟
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

步骤2:简化MainPage.xaml.cs,移除无用事件

namespace YourNamespace
{
    public partial class MainPage : ContentPage
    { 
        public MainPage()
        {
            InitializeComponent();
            BindingContext = new ViewModels.PingViewModel();       
        }
    }
}

步骤3:调整MainPage.xaml,绑定动态文本与单一命令

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YourNamespace.MainPage">

    <StackLayout Padding="20" Spacing="15">
        <Entry  x:Name="IPEntry"
                Text="{Binding Ip}"
                Placeholder="IP Address"                    
                HorizontalOptions="Center"
                VerticalOptions="Center" 
                WidthRequest="200" />

        <Button
            x:Name="togglePingBtn"
            Text="{Binding ButtonText}"
            Command="{Binding TogglePingCommand}"            
            HorizontalOptions="Center" />

        <ListView
            x:Name="listViewRes"
            HorizontalScrollBarVisibility="Always"
            HeightRequest="400"
            WidthRequest="400"
            VerticalScrollBarVisibility="Always"
            ItemsSource="{Binding PingCollection}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout Orientation="Horizontal" Spacing="10">
                            <Label Text="{Binding Status_ip}" WidthRequest="100" />
                            <Label Text="{Binding IPAddress}" WidthRequest="120" />
                            <Label Text="{Binding TTL}" WidthRequest="50" />
                            <Label Text="{Binding ResponseTime}" WidthRequest="80" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

步骤4:PingData.cs保持原结构(无需修改)

public class PingData
{
    public string IPAddress { get; set; }
    public string Status_ip { get; set; }
    public string TTL { get; set; }
    public string ResponseTime { get; set; }
    public int Count { get; set; }
}

关键改进说明

  1. 异步安全:使用CancellationTokenSource实现Ping任务的安全取消,避免线程冲突
  2. UI响应:所有异步操作使用await,彻底解决UI阻塞问题
  3. 数据正确性:每次Ping创建新的PingData实例,保证列表条目独立无覆盖
  4. 动态UI:按钮文本随IsRunning状态自动切换,提升用户体验
  5. MVVM规范:移除冗余的Clicked事件,完全使用Command绑定,符合MVVM设计原则

内容的提问来源于stack exchange,提问作者Zaid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 20:50:58