Xamarin按钮命令(在ListView.ItemTemplate中)未触发

6
我在项目中有一个XAML视图和一个视图模型。该项目是一个秒表,当按下“圈数”按钮时,它会向ObservableCollection添加一个对象,该对象作为ListView显示在视图中。
在ListView中,我添加了一个按钮以删除其中一个集合项。它具有绑定为“DeleteTimingCommand”的命令,并具有绑定为“Position”的CommandParameter,这是我要使用的标识符,以便从集合中删除对象。
DeleteTimingCommand位于ViewModel构造函数中,并设置为触发名为“DeleteTiming”的方法。然后,此方法负责实际删除操作。
但是,我的代码根本无法触发DeleteTiming()方法!无论我在哪里放置断点,都没有触发它。我按下按钮,什么也不会发生。
某些东西没有正确连接。有人可以指点我正确的方向吗?
XAML
 <?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" 
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
    x:Class="TechsportiseApp.Views.Timer" Title="Timer">
    <StackLayout VerticalOptions="Start" HorizontalOptions="FillAndExpand">
        <StackLayout Orientation="Horizontal">
            <Label Text="{Binding ElapsedTime}" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center" FontSize="40"/>
            <Button Command="{Binding LapCommand}" BackgroundColor="#eca400" IsVisible="{Binding EndVisibility}" Image="Scanning.png" WidthRequest="50" HeightRequest="50"/>
        </StackLayout>
        <Button x:Name="buttonStart" Text="Start Race" Command="{Binding StartTimerCommand}" IsVisible="{Binding StartVisibility}" />
        <Button x:Name="buttonEnd" Text="End Race" Command="{Binding EndTimerCommand}" IsVisible="{Binding EndVisibility}" />
        <Button x:Name="buttonSubmit" Text="Submit Results" Command="{Binding EndTimerCommand}" IsVisible="{Binding SubmitVisibility}" />
        <BoxView HeightRequest="1" Color="Silver" HorizontalOptions="FillAndExpand" />
        <Label Text="YOUR RESULTS" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center" FontSize="Small" FontAttributes="Bold"/>
        <BoxView HeightRequest="1" Color="Silver" HorizontalOptions="FillAndExpand" />

        <ListView ItemsSource="{Binding Timings}"
        SeparatorVisibility="None"
        HasUnevenRows="true">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid RowSpacing="3" ColumnSpacing="3">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="50" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="50" />
                            </Grid.ColumnDefinitions>
                            <Label x:Name="Pos" Text="{Binding Position}" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"  Grid.Row="0" Grid.Column="0" FontSize="Large" FontAttributes="Bold"/>
                            <Label Text="{Binding Elapsed}" VerticalTextAlignment="Center" Grid.Row="0" Grid.Column="1"  FontSize="Large" />
                            <Button Image="trash.png" BackgroundColor="Red" WidthRequest="50" HeightRequest="50" Command="{Binding DeleteTimingCommand}" CommandParameter="{Binding Position}" Grid.Row="0" Grid.Column="2" />
                            <BoxView HeightRequest="1" Color="Silver" HorizontalOptions="FillAndExpand" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" />

                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </StackLayout>
</ContentPage>

视图模型

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Timers;
using System.Windows.Input;
using TechsportiseApp.Models;
using Xamarin.Forms;

namespace TechsportiseApp.ViewModels
{
    public class TimerViewModel : INotifyPropertyChanged
    {
        public Timer myTimer = new Timer();

        public ICommand StartTimerCommand { get; set; }
        public ICommand EndTimerCommand { get; set; }
        public ICommand LapCommand { get; set; }
        public ICommand DeleteTimingCommand { get; set; }

        public TimerViewModel()
        {
            StartTimerCommand = new Command(StartTimer);
            EndTimerCommand = new Command(EndTimer);
            LapCommand = new Command(LapButton);
            DeleteTimingCommand = new Command<int>(DeleteTiming);
            Timings = new ObservableCollection<Timing>();
            LapPosition = 1;
            StartVisibility = true;
            EndVisibility = false;
            SubmitVisibility = false;
        }


        //TimeSpan _elapsedTime;
        //public TimeSpan ElapsedTime
        //{
        //    get {              
        //        return _elapsedTime;
        //    }
        //    set
        //    {
        //        if (_elapsedTime == value)
        //            return;

        //        _elapsedTime = value;
        //        OnPropertyChanged("ElapsedTime");
        //    }
        //}

        string _elapsedTime;
        public String ElapsedTime
        {
            get
            {
                if (_elapsedTime != null)
                {
                    return _elapsedTime;
                }
                else
                {
                    _elapsedTime = "00:00:00.00";
                    return _elapsedTime;
                }

            }
            set
            {
                if (_elapsedTime == value)
                    return;

                _elapsedTime = value;
                OnPropertyChanged("ElapsedTime");
            }
        }

        DateTime _currentTime;
        public DateTime CurrentTime
        {
            get { return _currentTime; }
            set
            {
                if (_currentTime == value)
                    return;

                _currentTime = value;
                OnPropertyChanged("CurrentTime");
            }
        }

        bool _startVisibility;
        public bool StartVisibility
        {
            get { return _startVisibility; }
            set
            {
                if (_startVisibility == value)
                    return;

                _startVisibility = value;
                OnPropertyChanged("StartVisibility");
            }
        }

        bool _endVisibility;
        public bool EndVisibility
        {
            get { return _endVisibility; }
            set
            {
                if (_endVisibility == value)
                    return;

                _endVisibility = value;
                OnPropertyChanged("EndVisibility");
            }
        }

        bool _submitVisibility;
        public bool SubmitVisibility
        {
            get { return _submitVisibility; }
            set
            {
                if (_submitVisibility == value)
                    return;

                _submitVisibility = value;
                OnPropertyChanged("SubmitVisibility");
            }
        }

        DateTime _raceStartTime;
        public DateTime RaceStartTime
        {
            get { return _raceStartTime; }
            set
            {
                if (_raceStartTime == value)
                    return;

                _raceStartTime = value;
                OnPropertyChanged("RaceStartTime");
            }
        }

        DateTime _lapTime;
        public DateTime LapTime
        {
            get { return _lapTime; }
            set
            {
                if (_lapTime == value)
                    return;

                _lapTime = value;
                OnPropertyChanged("LapTime");
            }
        }

        ObservableCollection<Timing> _timings;
        public ObservableCollection<Timing> Timings
        {
            get
            {
                //var sortedtimings = new ObservableCollection<Timing>(_timings.OrderBy(c => c.Position));
                var sortedtimings = new ObservableCollection<Timing>(_timings.OrderByDescending(c => c.Position));
                _timings = sortedtimings;
                return _timings;
            }
            set
            {
                if (_timings != value)
                {
                    _timings = value;
                    OnPropertyChanged("Timings");
                }
            }
        }

        int _lapPosition;
        public int LapPosition
        {
            get { return _lapPosition; }
            set
            {
                if (_lapPosition == value)
                    return;

                _lapPosition = value;
                OnPropertyChanged("LapPosition");
            }
        }



        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            var changed = PropertyChanged;
            if (changed != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        void StartTimer()
        {
            RaceStartTime = DateTime.Now;
            myTimer.Elapsed += new ElapsedEventHandler(DisplayTimeEvent);
            myTimer.Interval = 10; // 1000 ms is one second
            myTimer.Start();
            StartVisibility = false;
            EndVisibility = true;
            //ElapsedTime = myTimer.Elapsed.Milliseconds() += new ElapsedEventHandler(DisplayTimeEvent);
        }

        void EndTimer()
        {
            myTimer.Stop();
            EndVisibility = false;
            SubmitVisibility = true;
            //ElapsedTime = myTimer.Elapsed.Milliseconds() += new ElapsedEventHandler(DisplayTimeEvent);
        }

        void DisplayTimeEvent(object source, ElapsedEventArgs e)
        {
            TimeSpan _elapsed;
            _elapsed = e.SignalTime - RaceStartTime;

            string hours = _elapsed.Hours.ToString().PadLeft(2, '0');
            string minutes = _elapsed.Minutes.ToString().PadLeft(2, '0');
            string seconds = _elapsed.Seconds.ToString().PadLeft(2, '0');
            int _hundredths = _elapsed.Milliseconds / 10;

            string hundredths = _hundredths.ToString().PadLeft(2, '0');
            _elapsedTime = hours + ":" + minutes + ":" + seconds + "." + hundredths;
            ElapsedTime = _elapsedTime;
            OnPropertyChanged("ElapsedTime");
        }

        void LapButton()
        {
            var lap = new Timing
            {
                Id = 0,
                RaceId = 0,
                StartTime = RaceStartTime,
                EndTime = DateTime.Now,
                Elapsed = ElapsedTime,
                Position = LapPosition,
                Status = 0
            };
            Timings.Add(lap);

            OnPropertyChanged("Timings");
            LapPosition = LapPosition + 1;
            var listcheck = Timings.Count;

        }

        void DeleteTiming(int position)
        {
            foreach (var timing in Timings)
            {
                if (timing.Position == position)
                {
                    Timings.Remove(timing);                   
                    break;
                }
            }

            var NewPosition = Timings.Count();
            foreach (var timing in Timings)
            {
                timing.Position = NewPosition;
                NewPosition = NewPosition - 1;
            }

            OnPropertyChanged("Timings");
        }
    }
}

1
你的列表中的每个元素都绑定到一个Timing对象,并且你在TimerViewModel类中定义了你的命令。 - Jason
1个回答

20
根据当前代码,表单框架将尝试在相应的“Timing”对象中查找“DeleteTimingCommand”。为了避免这种情况,您需要在绑定中将父视图模型指定为源。请向父元素添加名称引用属性:
<ContentPage x:Name="ParentView" xmlns="http://xamarin.com/sch ..

并且,将您的绑定更改为:

<Button Image="trash.png".. Command="{Binding BindingContext.DeleteTimingCommand, Source={x:Reference ParentView}}" CommandParameter="{Binding Position}" .. />

这样,表单框架将知道在父视图的视图模型中查找命令,即TimerViewModel


我是Xamarin的初学者。您能否请解释一下“Command”属性和“CommandParameter”的区别。我试图找到答案,但没有得到一个恰当的回答。 - Mohan Perera
1
@MohanPerera:您将“Command”绑定到视图模型上的属性,该属性提供了类型为“Command”的实例,而绑定的“CommandParameter”则充当命令的“Execute”/“CanExecute”方法的参数/参数。 - Sharada Gururaj
1
@MohanPerera:我建议您通过此链接查看更详细的示例。https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/commanding#using-command-parameters - Sharada Gururaj
@SharadaGururaj,你太棒了,这对我有用,谢谢!! - Raj K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接