Binding to call a method of the binding class from a button.

JoeHonourJoeHonour GBMember
edited August 2015 in Xamarin.Forms

Hey,

So i have a View that i have bound to a List of Timer objects called Timers (custom class i have made), and in the view i have added a start and remove button. when a user clicks start i want them to be able to call the relevant timer object associated with the button underlying method startTimer(). How can i do this?

View code:

<ListView ItemsSource="{Binding Timers, Mode=TwoWay}" SeparatorVisibility="None">
    <ListView.ItemTemplate>
        <DataTemplate>
            <ViewCell>
                <StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal">
                    <StackLayout Padding="10,0,0,0" VerticalOptions="StartAndExpand" Orientation="Vertical">
                        <Label Text="{Binding _name, Mode=TwoWay}" YAlign="Center"/>
                        <Label Text="{Binding _startTime, Mode=TwoWay}" YAlign="Center" FontSize="Small"/>
                    </StackLayout>
                    <Button Text="Start" // call timers startTimer method></Button>
                    <Button Text="Remove"></Button>
                </StackLayout>
            </ViewCell>
        </DataTemplate>
    </ListView.ItemTemplate>

Timer Class:

public class Timer
{ 
    public int _startTime { get; set;} 
    public bool _hasStarted{ get; set; } 
    public string _name { get; set; }  

    public Timer (string name, int startTime, bool hasStarted = false)
    {
        _name = name; 
        _startTime = startTime; 
        _hasStarted = hasStarted; 
    }

    public void startTimer(){
        //do something here
    }
}

Best Answers

Answers

  • JoeHonourJoeHonour GBMember
    edited August 2015

    some reason it hasnt copied my view code out:

    so here it is:

    <ContentPage.Content>
    <StackLayout Orientation="Vertical">
    <ListView ItemsSource="{Binding Timers, Mode=TwoWay}" SeparatorVisibility="None">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal">
                        <StackLayout Padding="10,0,0,0" VerticalOptions="StartAndExpand" Orientation="Vertical">
                            <Label Text="{Binding _name, Mode=TwoWay}" YAlign="Center"/>
                            <Label Text="{Binding _startTime, Mode=TwoWay}" YAlign="Center" FontSize="Small"/>
                        </StackLayout>
                        <Button Text="Start"></Button>
                        <Button Text="Remove"></Button>
                    </StackLayout>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    <Button Text="Add New" Clicked="AddNewTimer"/>
    </StackLayout>
    </ContentPage.Content>
    

  • JoeHonourJoeHonour GBMember
    edited August 2015

    Hey, that was really helpful but it won't let me make an object of ICommand because it's an interface in step 4, and when i change it to just command it doesn' t work?

  • JoeHonourJoeHonour GBMember

    Made it work, thanks for your help. :smile:

  • AlexBekkerAlexBekker DEMember
    edited September 2015

    I ran into the same Issues and I have fiddled around for hours. The command just wont fire, the Buttons show up with proper naming tough.

    Here is the Code:

    PlotPage.xaml:
    `
    ContentPage x:Class="TabbedPages.PlotPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:TabbedPages"
    xmlns:oxy="clr-namespace:OxyPlot.XamarinForms;assembly=OxyPlot.XamarinForms"
    x:Name="ThePage">



    <ListView.ItemTemplate>





    </ListView.ItemTemplate>


    </ContentPage

    `

    Im Binding ItemsSource with
    this.SignalCellsListView.ItemsSource = PlotViewModel.SignalCellCollection;
    in the PlotPage.xaml.cs file

    ViewModel:
    `
    class PlotViewModel : ContentPage
    {
    public ICommand StartSeriesCommand{ get; set; }

    public static ObservableCollection<SignalCellData> SignalCellCollection = new         
    ObservableCollection<SignalCellData>()
        {
            new SignalCellData("Random 100"),
            new SignalCellData("Random 500"),
        };
    
    
        public PlotViewModel()
        {
            this.StartSeriesCommand= new Command(dummy);
    }
    
    
        public void dummy()
        {
            someAction;
        }
    

    }
    SignalCellData:
    public class SignalCellData
    {
    public SignalCellData(string name)
    {
    this.Name = name;
    }

        public string Name { private set; get; }
    }
    

    `

    Im greatfull for any help!

  • JoeHonourJoeHonour GBMember
    edited September 2015

    Try using a private/public variable, where you bind to the public variable, and in it's get method it gets the private ICommand if it's not null or if it is null, set the private ICommand to a new command and then return that.

    This is instead of initialising the command in a method, as i think that's what you are doing in the above code.

    private ICommand _yourcommand{ get; set;} public ICommand YourCommand { get { _yourcommand = _yourcommand ?? new Command(execute method here); return _yourcommand; } }

    Along with this, make sure in your xaml file you are using the correct syntax to bind, and that it is Mode=TwoWay.

  • AlexBekkerAlexBekker DEMember
    edited September 2015

    Oh wow, looks like I messed up the markdown really bad. Sorry for that!

    Thanks @JoeHonour for the help! I have incorporated your approach, but couldnt make it work.
    I think that I'm messing up the command bindings in XAML.

    Here is the corrected code:

    PlotPage.xaml:

    ContentPage x:Class="TabbedPages.PlotPage" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:TabbedPages" xmlns:oxy="clr-namespace:OxyPlot.XamarinForms;assembly=OxyPlot.XamarinForms" x:Name="ThePage"> <StackLayout x:Name="PlotPageStackLayout" Orientation="Horizontal" HorizontalOptions="CenterAndExpand"> <ListView x:Name="SignalCellsListView"> <ListView.ItemTemplate> <DataTemplate> <ViewCell x:Name="viewCell"> <Button Text="{Binding Path=Name}" Command="{Binding local:PlotViewModel.StartTimerCommand, Source={x:Reference Name=PlotPageStackLayout}}"> </Button> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage

    Im Binding ItemsSource with this.SignalCellsListView.ItemsSource = PlotViewModel.SignalCellCollection;
    in the PlotPage.xaml.cs file

    ViewModel:
    class PlotViewModel : ContentPage { public static List<SignalCellData> SignalCellCollection = new List<SignalCellData>() { new SignalCellData("Random 100"), new SignalCellData("Random 500") }; // private ICommand _startCommand{ get; set; } public ICommand StartCommand { get { startCommand= startCommand?? new Command(executeCommand); return startCommand; } } // public void executeCommand() { someAction; } }

    SignalCellData Class:
    public class SignalCellData { public SignalCellData(string name) { this.Name = name; } public string Name { private set; get; } }

  • JoeHonourJoeHonour GBMember

    Try changing your command binding on the button to {Binding commandname } or if that fails {OnClick commandname} and see if that brings any joy.

    Joe

  • AlexBekkerAlexBekker DEMember
    edited September 2015

    I tried both of the suggested solutions @JoeHonour
    Unfortunately it did not bring any joy, but thanks for the effort! I might try to do the binding in codebehind.

    Still, any other suggestions are very welcome.

  • JoeHonourJoeHonour GBMember

    Sorry that is probably the limit of my knowledge on this now! Try starting a new question with your problem, and one of the experts will probably be able to tell you whats wrong straight away!

    Joe

Sign In or Register to comment.