Xamarin 按钮命令(在 ListView.ItemTemplate 内)未触发 [英] Xamarin Button Command (inside of ListView.ItemTemplate) Not Firing

查看:19
本文介绍了Xamarin 按钮命令(在 ListView.ItemTemplate 内)未触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的项目中有一个 XAML 视图和一个视图模型.该项目是一个秒表,当按下 Lap 按钮时,它会向 ObservableCollection 添加一个对象,该对象在视图中显示为 ListView.

I have a XAML View and a View Model in my project. The project is a stopwatch and as a Lap button is pressed it adds an object to an ObservableCollection which is displayed in the view as a ListView.

在 ListView 中,我添加了一个按钮来删除集合项之一.它有一个绑定为DeleteTimingCommand"的命令和一个绑定为Position"的CommandParameter,这是我想用来从集合中删除对象的标识符.

In the ListView I have added a button to delete one of the Collection items. It has a Command with a Binding of "DeleteTimingCommand" and a CommandParameter with a Binding of "Position" which is the identifier I want to use in order to delete the object from the collection.

DeleteTimingCommand 位于 ViewModel 构造函数中,并设置为触发名为DeleteTiming"的方法.然后这个方法负责实际的删除.

The DeleteTimingCommand is in the ViewModel constructor and set to fire a method called "DeleteTiming". This method then takes care of the actual deletion.

但是,我根本无法让我的代码命中我的 DeleteTiming() 方法!无论我在哪里放置断点,都不会触发它.我按下按钮,没有任何反应.

However, I can't get my code to hit my DeleteTiming() method at all! No matter where I put a breakpoint, nothing is firing it. I press the button and nothing happens.

有些地方没有正确连接.有人能指出我正确的方向吗?

Something isn't hooked up right. Can anyone point me in the right direction?

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");
        }
    }
}

推荐答案

根据当前代码,表单框架将尝试在相应的 Timing 对象中查找 DeleteTimingCommand.为了解决这个问题,您必须在绑定中将父视图模型指定为源.

As per current code, the forms framework will try to look for DeleteTimingCommand in the corresponding Timing object. In order to get around that you will have to specify the parent view-model as source in the binding.

给父元素添加名称引用属性:

Add name reference attribute to the parent element:

<ContentPage x:Name="ParentView" xmlns="http://xamarin.com/sch ..

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

And, change your binding to:

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

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

This way the forms framework will know to look for the command in the parent-view's view model i.e. TimerViewModel.

这篇关于Xamarin 按钮命令(在 ListView.ItemTemplate 内)未触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆