Xamarin XAML命令不会被触发

时间:2017-11-15 22:28:11

标签: c# xaml xamarin.forms

我有一个Xamarin XAML内容页面,上面有一堆按钮。目的是让这些按钮执行我当前已编码到ViewModel中的命令。

问题是,命令没有触发。我在我的void方法中设置了断点,这些断点一直链接到我的构造函数。构造函数正常工作。当我单击该按钮时,断点不会在执行该过程的任务中被点击。

viewmodel的绑定工作正常,因为其他数据绑定到页面OK。

具体来说,void方法DeleteScan和DeleteTiming是我试图首先工作的方法。

顺便说一下,我有类似的代码在另一个视图中成功运行,但我无法解决这个视图/ viewmodel的错误。

有什么想法吗?

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.ResultsProcess" x:Name="ParentView" Title="Processing">
    <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
        <StackLayout HorizontalOptions="FillAndExpand" BackgroundColor="Red" Padding="2" IsVisible="{Binding Error}">
            <Label Text="{Binding ErrorMessage}" BackgroundColor="Red" TextColor="White" FontAttributes="Bold" FontSize="Small" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center" />
        </StackLayout>
        <ActivityIndicator IsVisible="{Binding IsBusy}" IsRunning="{Binding IsBusy}" Color="#80000000"/>
        <Label Text="Validation messages can go here" TextColor="Red" FontSize="Small" HorizontalOptions="FillAndExpand" HorizontalTextAlignment="Center" IsVisible="{Binding Invalid}" />
        <StackLayout Orientation="Horizontal" Padding="3" IsVisible = "{Binding AddVisibility}">
            <Button x:Name="buttonAddScan" Style="{StaticResource Buttons}"  Image="addmanual.png"  Text="Add Finisher"  IsVisible="{Binding AddVisibility}" HorizontalOptions="StartAndExpand" />       
            <Button x:Name="buttonAddTime" Style="{StaticResource Buttons}"  Image="addmanual.png" Text="Add Time"  IsVisible="{Binding AddVisibility}" HorizontalOptions="EndAndExpand"  />
        </StackLayout>

        <StackLayout Padding="5, 1" Orientation="Horizontal" IsVisible="{Binding AddScanVisibility}" HorizontalOptions="EndAndExpand" VerticalOptions="Center">
            <Label Text="Add Missing Finisher" FontAttributes="Bold" VerticalTextAlignment="Center" HorizontalTextAlignment="Start" FontSize="Small" />
            <Picker x:Name="pickerAboveBelow" Title="Pick" SelectedItem="{Binding AboveBelow}">
                <Picker.Items>
                    <x:String>Above</x:String>
                    <x:String>Below</x:String>
                </Picker.Items>
            </Picker>
            <Entry x:Name="entryAboveBelowPosition" Text="{Binding AboveBelowPosition}" HorizontalTextAlignment="Center" Placeholder="Pos" PlaceholderColor="Silver"  Keyboard="Numeric" WidthRequest="70" HorizontalOptions="Start" />
            <Entry x:Name="entryMissingBib" Text="{Binding MissingBib}" HorizontalTextAlignment="Center" Placeholder="Bib" PlaceholderColor="Silver"  Keyboard="Numeric" WidthRequest="70" HorizontalOptions="Start" />
            <Button Command="{Binding MissingFinisherCommand}" CommandParameter="{x:Reference entryMissingBib}" Image="addmanual.png" WidthRequest="50" HeightRequest="50" HorizontalOptions="End" />
        </StackLayout>

        <StackLayout Padding="5, 1" Orientation="Horizontal" IsVisible="{Binding AddScanVisibility}" HorizontalOptions="EndAndExpand" VerticalOptions="Center">
            <Label Margin = "3" Text="Add Manual Time" FontAttributes="Bold" VerticalTextAlignment="Center" HorizontalTextAlignment="Start" FontSize="Small" IsVisible="{Binding SubmitVisibility}"/>
            <Entry Margin = "3"  Text="{Binding AddHH}" HorizontalTextAlignment="Center" Placeholder="HH" PlaceholderColor="Silver" IsVisible="{Binding SubmitVisibility}" Keyboard="Numeric" WidthRequest="50" HorizontalOptions="Start"/>
            <Label Margin = "3"  Text=":" HorizontalTextAlignment="Center" IsVisible="{Binding EndVisibility}" HorizontalOptions="Start"/>
            <Entry Margin = "3"  Text="{Binding AddMM}" HorizontalTextAlignment="Center" Placeholder="MM" PlaceholderColor="Silver" IsVisible="{Binding SubmitVisibility}" Keyboard="Numeric" WidthRequest="50" HorizontalOptions="Start"/>
            <Label Margin = "3"  Text=":" HorizontalTextAlignment="Center" IsVisible="{Binding EndVisibility}" HorizontalOptions="Start"/>
            <Entry Margin = "3"  Text="{Binding AddSS}" HorizontalTextAlignment="Center" Placeholder="SS" PlaceholderColor="Silver" IsVisible="{Binding SubmitVisibility}" Keyboard="Numeric" WidthRequest="50" HorizontalOptions="Start"/>
            <Button Command="{Binding ManualTimeCommand}" IsVisible="{Binding SubmitVisibility}" Image="addmanual.png" WidthRequest="50" HeightRequest="50" HorizontalOptions="End" Style="{StaticResource Buttons}" />
        </StackLayout>

        <ListView ItemsSource="{Binding Results}" SeparatorVisibility="None" HasUnevenRows="true"  IsVisible="true">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <Grid RowSpacing="0" ColumnSpacing="0">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                                <RowDefinition Height="Auto" />
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="60" />
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="40" />
                                <ColumnDefinition Width="140" />
                            </Grid.ColumnDefinitions>
                            <StackLayout Orientation="Vertical" Grid.Row="0" Grid.Column = "0" Grid.RowSpan="3" Margin="0,0,0,5">
                                <Label Text="{Binding ScanPosition}" FontSize="Large" FontAttributes="Bold" Margin="0" HorizontalOptions="Center" VerticalOptions="Start" TextColor="Red" />
                                <Button Image="trash.png" WidthRequest="30" HeightRequest="30" HorizontalOptions="Center" Command="{Binding DeleteScanCommand}" CommandParameter="{Binding ScanId}" />
                            </StackLayout>
                            <Label Text="{Binding FormattedName}"  Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2"  Margin="0,0,0,5" FontSize="Large" />
                            <Label Text="{Binding EntryBibNumber}" Grid.Column="1" Grid.Row="1" Margin="0,0,0,5" VerticalTextAlignment="Center" HorizontalTextAlignment="Start" FontSize="Large" TextColor="Teal" />

                            <Label Text="{Binding FormattedClub}"  Grid.Column="1" Grid.Row="2" Margin="0" FontSize="Small"  TextColor="Gray" HorizontalOptions="StartAndExpand" />
                            <Label Text="{Binding Category}"  Grid.Column="2" Grid.Row="2" Margin="0" FontSize="Small"  TextColor="Gray" HorizontalOptions="End" />
                            <StackLayout Orientation="Vertical" Grid.Row="0" Grid.Column = "3" Grid.RowSpan="3"  Margin="0,0,0,5">
                                <Label Text="{Binding Elapsed}"  HorizontalTextAlignment="End" FontSize="Large" FontAttributes="Bold" TextColor="Red" HorizontalOptions="Center"  VerticalOptions="Start" />
                                <Button Image="trash.png" WidthRequest="30" HeightRequest="30" VerticalOptions="Center" HorizontalOptions="Center" Command="{Binding DeleteTimingCommand}" CommandParameter="{Binding TimingId}" />
                            </StackLayout>
                            <BoxView HeightRequest="1" Color="#f4da9e" HorizontalOptions="FillAndExpand" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="4" />
                        </Grid>
                    </ViewCell>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <StackLayout Orientation="Horizontal" Padding="3">
            <Button x:Name="buttonSubmitProvisional" Text="Publish Provisional"  IsVisible="true" HorizontalOptions="StartAndExpand" Command="{Binding DeleteScanCommand}" CommandParameter="1"/>
            <Button x:Name="buttonSubmitFinal" Text="Publish Final"  IsVisible="true" HorizontalOptions="EndAndExpand" />
        </StackLayout>
    </StackLayout>
</ContentPage>

代码背后

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TechsportiseApp.API;
using TechsportiseApp.Views;
using TechsportiseApp.ViewModels;
using TechsportiseApp.Models;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace TechsportiseApp.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class ResultsProcess : ContentPage
    {
        public ResultsProcess(Race race)
        {
            InitializeComponent();
            var viewModel = new ResultsProcessViewModel(race);
            BindingContext = viewModel;

            ToolbarItems.Add(new ToolbarItem("Help", "help.png", async () =>
            {
                await Navigation.PushAsync(new ResultsProcessHelp());
            }, 0, 2));

        }
    }
}

ViewModel (删除了一些不重要的部分包含属性)

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.API;
using TechsportiseApp.Models;
using Xamarin.Forms;
using System.Threading.Tasks;
using TechsportiseApp.Helpers;

namespace TechsportiseApp.ViewModels
{
    public class ResultsProcessViewModel : INotifyPropertyChanged
    {

        public ICommand AddTimingCommand { get; set; }
        public ICommand AddScanCommand { get; set; }
        public ICommand DeleteTimingCommand { get; set; }
        public ICommand DeleteScanCommand { get; set; }
        public ICommand PublishProvisionalCommand { get; set; }
        public ICommand PublishFinalCommand { get; set; }
        public ICommand LoadResultsCommand { get; set; }
        public ICommand MissingFinisherCommand { get; set; }
        public ICommand MissingTimingCommand { get; set; }

        public int RaceId { get; set; }
        public DateTime RaceDate { get; set; }

        //public ResultsViewModel(Race race)
        public ResultsProcessViewModel(Race race)
        {
            AddTimingCommand = new Command(AddTiming);
            AddScanCommand = new Command(AddScan);
            DeleteTimingCommand = new Command<int>(DeleteTiming);
            DeleteScanCommand = new Command<int>(DeleteScan);
            PublishProvisionalCommand = new Command<int>(PublishProvisional);
            PublishFinalCommand = new Command<int>(PublishFinal);
            LoadResultsCommand = new Command<int>(LoadResults);
            MissingFinisherCommand = new Command<int>(MissingFinisher);
            MissingTimingCommand = new Command<int>(MissingTiming);

            Invalid = false;

            AddTimingVisibility = false;
            AddScanVisibility = false;
            AddVisibility = true;
            PublishProvisionalVisibility = false;
            PublishFinalVisibility = false;
            IsBusy = false;
            RaceId = race.Id;
            RaceDate = race.RaceDate;
            Scans = ScansAPI.GetScans(RaceId);
            Timings = TimingsAPI.GetTimings(RaceId);
            Entries = EntriesAPI.GetEntries(RaceId);
            LoadResults(RaceId);
        }



        ObservableCollection<Result> _results;
        public ObservableCollection<Result> Results
        {
            get
            {
                return _results;
            }
            set
            {
                if (_results != value)
                {
                    _results = value;
                    OnPropertyChanged("Results");
                }
            }
        }

        ObservableCollection<Scan> _scans;
        public ObservableCollection<Scan> Scans
        {
            get
            {
                return _scans;
            }
            set
            {
                if (_scans != value)
                {
                    _scans = value;
                    OnPropertyChanged("Scans");
                }
            }
        }

        ObservableCollection<Timing> _timings;
        public ObservableCollection<Timing> Timings
        {
            get
            {
                return _timings;
            }
            set
            {
                if (_timings != value)
                {
                    _timings = value;
                    OnPropertyChanged("Timings");
                }
            }

        }

        ObservableCollection<RaceEntry> _entries;
        public ObservableCollection<RaceEntry> Entries
        {
            get
            {
                return _entries;
            }
            set
            {
                if (_entries != value)
                {
                    _entries = value;
                    OnPropertyChanged("Entries");
                }
            }
        }

        bool _invalid;
        public bool Invalid
        {
            get { return _invalid; }
            set
            {
                if (_invalid == value)
                    return;

                _invalid = value;
                OnPropertyChanged("Invalid");
            }
        }

        string _validationError;
        public string ValidationError
        {
            get { return _validationError; }
            set
            {
                if (_validationError == value)
                    return;

                _validationError = value;
                OnPropertyChanged("ValidationError");
            }
        }

        string _errorMessage;
        public string ErrorMessage
        {
            get { return _errorMessage; }
            set
            {
                if (_errorMessage == value)
                    return;

                _errorMessage = value;
                OnPropertyChanged("ErrorMessage");
            }
        }

        public Race SelectedRace { get; set; }

        private bool _raceCountZero;
        public bool RaceCountZero
        {
            get { return _raceCountZero; }
            set
            {
                if (_raceCountZero == value)
                    return;

                _raceCountZero = value;
                OnPropertyChanged("RaceCountZero");
            }
        }

        ObservableCollection<Race> _races;
        public ObservableCollection<Race> Races
        {
            get
            {
                try
                {
                    var racelist = RacesAPI.GetRaces();
                    var sortedracelist = new ObservableCollection<Race>(racelist.OrderBy(c => c.Name));
                    var racecount = racelist.Count();
                    if (racecount == 0)
                    {
                        RaceCountZero = true;
                    }
                    else
                    {
                        RaceCountZero = false;
                    }

                    return racelist;
                }
                catch
                {
                    Invalid = true;
                    ValidationError = "Error getting Race List. No internet connection available.";
                }


                return _races;


            }
            set
            {
                if (_races != value)
                {
                    _races = value;
                    OnPropertyChanged("Races");
                }
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

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



        void AddTiming()
        {

            //Do stuff when adding a timing. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection



        }

        void AddScan()
        {

            //Do stuff when adding a timing. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection



        }

        void DeleteTiming(int timingid)
        {

            //Do stuff when deleting a timing. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection
            Task.Run(() =>
            {
                try
                {

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot delete a timing whilst you are offline");

                    //We are good to go
                    else
                    {
                        var deletetiming =  TimingsAPI.DeleteTiming(timingid);

                        if(deletetiming.Code != "200")
                            throw new Exception("Error deleting timing");
                    }
                }
                catch (Exception ex)
                {

                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;

                    });

                    return;
                }
                finally
                {                    
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    OnPropertyChanged("Timings");
                }
            });


        }

        void DeleteScan(int scanid)
        {

            //Do stuff when deleting a scan. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection
            Task.Run(() =>
            {
                try
                {

                    Device.BeginInvokeOnMainThread(() => IsBusy = true);
                    var IsThereConnection = GlobalFunctions.CheckForInternetConnection();

                    if (IsThereConnection == false)
                        throw new Exception("You cannot delete a scan whilst you are offline");

                    //We are good to go
                    else
                    {
                        var deletetiming = TimingsAPI.DeleteTiming(scanid);

                        if (deletetiming.Code != "200")
                            throw new Exception("Error deleting scan");
                    }
                }
                catch (Exception ex)
                {

                    Device.BeginInvokeOnMainThread(() =>
                    {
                        ValidationError = ex.Message;
                        Invalid = true;

                    });

                    return;
                }
                finally
                {
                    Device.BeginInvokeOnMainThread(() => IsBusy = false);
                    OnPropertyChanged("Scans");
                }
            });


        }

        void PublishProvisional(int raceid)
        {

            //Do stuff when submitting provisional. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection



        }

        void PublishFinal(int raceid)
        {

            //Do stuff when submitting final. It needs to do all this in the observable collection. Then when we submit, we'll update all scans, timings etc with whats in the collection



        }

        void MissingFinisher(int raceid)
        {




        }

        void MissingTiming(int raceid)
        {




        }

        void LoadResults(int raceid)
        {


            var results = new ObservableCollection<Result>();



                //Start with the timings
                foreach(Timing timing in Timings)
                {
                    var result = new Result();

                    //Basic details
                    result.RaceId = RaceId;
                    result.RaceDate = RaceDate;
                    result.Status = "Processing";

                    //Timing Data
                    result.TimingId = timing.Id;
                    result.TimingPosition = timing.Position;
                    result.TimingStatus = timing.Status;
                    result.StartTime = timing.StartTime;
                    result.EndTime = timing.EndTime;

                    var elapsed = result.EndTime - result.StartTime;

                    string elapsedhours = elapsed.Hours.ToString();
                    string elapsedminutes = elapsed.Minutes.ToString();
                    string elapsedseconds = elapsed.Seconds.ToString();
                    string elapsedmillis = elapsed.Milliseconds.ToString().Substring(0,2);

                    if (elapsedhours.Length==1) { elapsedhours = "0" + elapsedhours; }
                    if (elapsedminutes.Length == 1) { elapsedminutes = "0" + elapsedminutes; }
                    if (elapsedseconds.Length == 1) { elapsedseconds = "0" + elapsedseconds; }
                    if (elapsedmillis.Length == 1) { elapsedmillis = "0" + elapsedmillis; }

                    result.Elapsed = elapsedhours + ":" + elapsedminutes + ":" + elapsedseconds + "." + elapsedmillis;



                        results.Add(result);
                    }

                //Add in the scans
                foreach (Result result1 in results)
                {
                var scan = Scans.FirstOrDefault(p => p.Position == result1.TimingPosition);
                    if(scan != null)
                    {
                        result1.ScanId = scan.Id;
                        result1.ScanPosition = scan.Position;
                        result1.ScanStatus = scan.Status;
                        result1.ScanBibNumber = scan.BibNumber;       
                    }
                    else
                    {
                        result1.ScanId = 0;
                        result1.ScanPosition = 0;
                        result1.ScanStatus = 99;
                        result1.ScanBibNumber = "UNKNOWN";
                    }
                }

                //Add any scans which there are no times for (Higher than count)
                var timingscount = Timings.Count();
                var notimescans = new ObservableCollection<Scan>();
                foreach (Scan scan in Scans)
                {
                    if (scan.Position > timingscount)
                    {
                        var newresult = new Result();

                        newresult.RaceId = RaceId;
                        newresult.RaceDate = RaceDate;
                        newresult.Status = "Processing";
                        newresult.ScanId = scan.Id;
                        newresult.ScanPosition = scan.Position;
                        newresult.ScanStatus = scan.Status;
                        newresult.ScanBibNumber = scan.BibNumber;

                        newresult.TimingId = 0;
                        newresult.TimingPosition = 99999;
                        newresult.TimingStatus = 99;
                        newresult.StartTime = DateTime.Now;
                        newresult.EndTime = newresult.StartTime;

                        var elapsed = newresult.EndTime - newresult.StartTime;

                        string elapsedhours = elapsed.Hours.ToString();
                        string elapsedminutes = elapsed.Minutes.ToString();
                        string elapsedseconds = elapsed.Seconds.ToString();
                        string elapsedmillis = elapsed.Milliseconds.ToString();

                        newresult.Elapsed = elapsedhours + ":" + elapsedminutes + ":" + elapsedseconds + ":" + elapsedmillis;


                        results.Add(newresult);
                    }
                }

                //Then add in the entries
                foreach (Result result2 in results)
                {

                    var entry = Entries.FirstOrDefault(p => p.BibNumber == result2.ScanBibNumber);
                    if (entry != null)
                    {
                        result2.EntryId = entry.Id;
                        result2.FirstName = entry.FirstName;
                        result2.LastName = entry.LastName;
                        result2.FormattedName = entry.FirstName + " " + entry.LastName.ToUpper();
                        result2.Gender = entry.Gender;
                        result2.DateOfBirth = entry.DateOfBirth;
                        result2.Club = entry.Club;
                        result2.Team = entry.Team;
                        result2.EntryBibNumber = entry.BibNumber;
                    }
                    else
                    {
                        result2.EntryId = 0;
                        result2.FirstName = "Unknown";
                        result2.LastName = "ATHLETE";
                        result2.Gender = "Unknown";
                        result2.DateOfBirth = DateTime.Now;
                        result2.Club = "";
                        result2.Team = "";
                        result2.EntryBibNumber = "Unknown";
                    }

                }
            var sortedresults = new ObservableCollection<Result>(results.OrderBy(c => c.TimingPosition));
            Results = sortedresults;


        }



    }
}

0 个答案:

没有答案