question

jasfour04 avatar image
0 Votes"
jasfour04 asked RobCaplan edited

My custom DatePicker renderer with new UIBarButtonItem buttons is not working

This is my Custom renderer for date picker in ios. What am I doing wrong that UIBarButton click events are not being triggered

 // ------------------------------------------------------------
 // Copyright (c) Ossiaco Inc. All rights reserved.
 // ------------------------------------------------------------
    
 using System;
 using dcbel.Mobile.Controls;
 using dcbel.Mobile.iOS.Extensions;
 using dcbel.Mobile.iOS.Renderers;
 using UIKit;
 using Xamarin.Forms;
 using Xamarin.Forms.Platform.iOS;
    
 [assembly: ExportRenderer(typeof(CustomDatePicker), typeof(CustomDatePickerRenderer))]
    
 namespace dcbel.Mobile.iOS.Renderers
 {
     /// <summary>
     /// An extended date picker renderer.
     /// </summary>
     ///
     /// <seealso cref="T:Xamarin.Forms.Platform.iOS.DatePickerRenderer"/>
     public class CustomDatePickerRenderer : DatePickerRenderer
     {
         /// <summary>
         /// Executes the element changed action.
         /// </summary>
         ///
         /// <param name="e"> An ElementChangedEventArgs{DatePicker} to process. </param>
         protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
         {
             base.OnElementChanged(e);
    
             if (this.Control?.InputAccessoryView != null && e?.NewElement is CustomDatePicker datePicker)
             {
                 if (this.Control.InputAccessoryView is UIToolbar toolbar)
                 {
                     var buttonTextAttributes = new UITextAttributes()
                     {
                         Font = UIFont.FromName("SFStrong", 15),
                         TextColor = UIColorExtensions.FromHex("5A5E62"),
                     };
    
                     using var doneButton = new UIBarButtonItem(datePicker.DoneButtonText, UIBarButtonItemStyle.Done, this.DoneButtonAction);
                     using var cancelButton = new UIBarButtonItem(datePicker.CancelButtonText, UIBarButtonItemStyle.Done, this.CancelButtonAction);
                     using var title = new UIBarButtonItem(datePicker.TitleText, UIBarButtonItemStyle.Plain, null) { Enabled = false };
                     using var space = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
    
                     doneButton.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                     title.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                     title.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Disabled);
                     cancelButton.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                     toolbar.SetItems(new UIBarButtonItem[] { cancelButton, space, title, space, doneButton }, true);
    
                     this.Control.InputAccessoryView = toolbar;
                 }
             }
         }
    
         private void CancelButtonAction(object sender, EventArgs eventArgs)
         {
             this.Control.ResignFirstResponder();
             this.Element.Unfocus();
         }
    
         private void DoneButtonAction(object sender, EventArgs eventArgs)
         {
             this.Control.ResignFirstResponder();
         }
     }
 }

Can someone please help me figure this one out. I tried adding a new click even to the existing Done button that comes with the date picker toolbar and that works. For some reason that I can't figure out the new buttons are not triggering their events when I click them

dotnet-xamarin
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I test with your code , the new button click event triggers as expected .
Could you provide a basic ,minimal project to us for reproducing the issue ?

0 Votes 0 ·

How did you text it btw? Maybe there is something weird going on in my underlying XAML or csproj?

0 Votes 0 ·
jasfour04 avatar image
0 Votes"
jasfour04 answered jasfour04 edited

I went ahead and tried using target and action from an object c perspective and it worked. Why is native C# xamarin not working for me

 using var doneButton = new UIBarButtonItem(datePicker.DoneButtonText, UIBarButtonItemStyle.Done, this, ObjCRuntime.Selector.FromHandle(ObjCRuntime.Selector.GetHandle("DoneButtonAction:")));
                     using var cancelButton = new UIBarButtonItem(datePicker.CancelButtonText, UIBarButtonItemStyle.Done, this, ObjCRuntime.Selector.FromHandle(ObjCRuntime.Selector.GetHandle("CancelButtonAction:")));
                     using var title = new UIBarButtonItem(datePicker.TitleText, UIBarButtonItemStyle.Plain, null) { Enabled = false };
                     using var space = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);
    
                     doneButton.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                     title.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                     title.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Disabled);
                     cancelButton.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                     toolbar.SetItems(new UIBarButtonItem[] { cancelButton, space, title, space, doneButton }, true);
                 }
    
                 if (this.Control.InputView is UIDatePicker uiDatePicker)
                 {
                     uiDatePicker.Mode = UIDatePickerMode.DateAndTime;
                 }
             }
         }
    
         [Action("CancelButtonAction:")]
         private void CancelButtonAction(NSObject sender)
         {
             this.Control.ResignFirstResponder();
             this.Element.Unfocus();
         }
    
         [Action("DoneButtonAction:")]
         private void DoneButtonAction(NSObject sender)
         {
             this.Control.ResignFirstResponder();
         }


· 7
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

It is weird, if possible could you provide us a minimal, reproducible project ?
Anyway , your problem has been solved (at least has a workaround ) could you mark it as answer ?

0 Votes 0 ·

What is the best way to provide you with the minimal project

0 Votes 0 ·

You can upload it on github and attach the repo link here .

0 Votes 0 ·
Show more comments
ColeXia-MSFT avatar image
0 Votes"
ColeXia-MSFT answered ColeXia-MSFT edited

Hello,

Welcome to Microsoft Q&A!

The following code works perfectly on my side .

Forms


public class CustomDatePicker : DatePicker
    {
        public string DoneButtonText
        {
            get { return (string)GetValue(DoneButtonTextProperty); }
            set { SetValue(DoneButtonTextProperty, value); }
        }
        public static readonly BindableProperty DoneButtonTextProperty = BindableProperty.Create("DoneButtonText", typeof(string), typeof(CustomDatePicker));

        public string CancelButtonText
        {
            get { return (string)GetValue(CancelButtonTextProperty); }
            set { SetValue(CancelButtonTextProperty, value); }
        }
        public static readonly BindableProperty CancelButtonTextProperty = BindableProperty.Create("CancelButtonText", typeof(string), typeof(CustomDatePicker));

        public string TitleText
        {
            get { return (string)GetValue(TitleTextProperty); }
            set { SetValue(TitleTextProperty, value); }
        }
        public static readonly BindableProperty TitleTextProperty = BindableProperty.Create("TitleText", typeof(string), typeof(CustomDatePicker));
    }

//xaml

xmlns:local="clr-namespace:FormsProjectName"
<local:CustomDatePicker
        MinimumDate="01/01/2018" 
        MaximumDate="12/31/2018"
        Date="06/21/2018"
        TitleText="Im title"
        DoneButtonText="done"
        CancelButtonText="cancel"/>


iOS



[assembly: ExportRenderer(typeof(CustomDatePicker), typeof(CustomDatePickerRenderer))]

namespace App31.iOS
{
    /// <summary>
    /// An extended date picker renderer.
    /// </summary>
    ///
    /// <seealso cref="T:Xamarin.Forms.Platform.iOS.DatePickerRenderer"/>
    public class CustomDatePickerRenderer : DatePickerRenderer
    {
        /// <summary>
        /// Executes the element changed action.
        /// </summary>
        ///
        /// <param name="e"> An ElementChangedEventArgs{DatePicker} to process. </param>
        protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
        {
            base.OnElementChanged(e);

            if (this.Control?.InputAccessoryView != null && e?.NewElement is CustomDatePicker datePicker)
            {
                if (this.Control.InputAccessoryView is UIToolbar toolbar)
                {
                    var buttonTextAttributes = new UITextAttributes()
                    {
                        Font = UIFont.FromName("SFStrong", 15),
                        TextColor = UIColor.Red
                    };

                     var doneButton = new UIBarButtonItem(datePicker.DoneButtonText, UIBarButtonItemStyle.Done, this.DoneButtonAction);
                     var cancelButton = new UIBarButtonItem(datePicker.CancelButtonText, UIBarButtonItemStyle.Done, this.CancelButtonAction);
                     var title = new UIBarButtonItem(datePicker.TitleText, UIBarButtonItemStyle.Plain, null) { Enabled = false };
                     var space = new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace);

                    doneButton.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                    title.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                    title.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Disabled);
                    cancelButton.SetTitleTextAttributes(buttonTextAttributes, UIControlState.Normal);
                    toolbar.SetItems(new UIBarButtonItem[] { cancelButton, space, title, space, doneButton }, true);

                    this.Control.InputAccessoryView = toolbar;
                }
            }
        }

        private void CancelButtonAction(object sender, EventArgs eventArgs)
        {
            this.Control.ResignFirstResponder();
            this.Element.Unfocus();
        }

        private void DoneButtonAction(object sender, EventArgs eventArgs)
        {
            this.Control.ResignFirstResponder();
        }
    }
}



If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

jasfour04 avatar image
0 Votes"
jasfour04 answered jasfour04 edited

This is what my view currently looks like, could the layout be the problem? @ColeXia-MSFT

 <?xml version="1.0" encoding="utf-8" ?>
 <local:ViewBase 
     xmlns="http://xamarin.com/schemas/2014/forms"
     xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
     xmlns:resources="clr-namespace:dcbel.Mobile.Resx"
     xmlns:local="clr-namespace:dcbel.Mobile.Views"
     xmlns:control="clr-namespace:dcbel.Mobile.Controls"
     xmlns:vm="clr-namespace:dcbel.Mobile.ViewModels.ChargingSchedule"
     xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
     xmlns:svgimage="clr-namespace:FFImageLoading.Svg.Forms;assembly=FFImageLoading.Svg.Forms"
     x:Class="dcbel.Mobile.Views.ChargingSchedule.ListChargingScheduleView"
     x:TypeArguments="vm:ListChargingScheduleViewModel"
     ios:Page.UseSafeArea="True"
     NavigationPage.HasNavigationBar="False">
     <ContentPage.Content>
         <FlexLayout Direction="Column" AlignItems="Center" BackgroundColor="{AppThemeBinding Light=#FFFFFF, Dark=#00000}">
             <control:TitleBar x:Name="TitleBar" Title="{x:Static resources:AppResources.EVDCCharging}" BackButtonImageSource="resource://dcbel.Mobile.Resources.arrowleft.svg"/>
             <!--<FlexLayout x:Name="NewChargeLayout" Direction="Column" AlignItems="Center" JustifyContent="Center" IsVisible="False">
                 <FlexLayout Direction="Row" JustifyContent="Center" FlexLayout.Basis="20%">
                     <svgimage:SvgCachedImage Source="resource://dcbel.Mobile.Resources.calendar.svg" HeightRequest="100"/>
                 </FlexLayout>
                 <FlexLayout Direction="Row" JustifyContent="Center" FlexLayout.Basis="10%">
                     <StackLayout Orientation="Vertical" FlexLayout.Basis="50%">
                         <Label Text="{x:Static resources:AppResources.ChargingDesc}" HorizontalTextAlignment="Center" FontSize="18" FontAttributes="Bold" TextColor="{AppThemeBinding Light=#777A7F, Dark=#FFFFFF}" />
                     </StackLayout>
                 </FlexLayout>
             </FlexLayout>-->
             <AbsoluteLayout FlexLayout.Basis="70%">
                 <ListView x:Name="ChargingSchedules" RowHeight="64" CachingStrategy="RecycleElement">
                     <ListView.ItemTemplate>
                         <DataTemplate>
                             <ViewCell>
                                 <FlexLayout Direction="Column" AlignItems="Center">
                                     <FlexLayout Direction="Row" AlignItems="Start" JustifyContent="SpaceBetween" FlexLayout.Basis="100%" Margin="0,10,0,0">
                                         <svgimage:SvgCachedImage Source="resource://dcbel.Mobile.Resources.schedulecalendar.svg" HeightRequest="25" FlexLayout.Basis="15%"/>
                                         <FlexLayout Direction="Column" FlexLayout.Basis="70%">
                                             <Label FormattedText="" Text="{Binding DateTime, StringFormat='{0:D}'}" FontSize="18" TextColor="#5A5E62" VerticalTextAlignment="Center" HorizontalTextAlignment="Start" />
                                             <Label FontSize="16" TextColor="#94989D" VerticalTextAlignment="Center" HorizontalTextAlignment="Start" >
                                                 <Label.FormattedText>
                                                     <MultiBinding StringFormat="{}{0:t}, {1}">
                                                         <Binding Path="DateTime"/>
                                                         <Binding Path="Range"/>
                                                     </MultiBinding>
                                                 </Label.FormattedText>
                                             </Label>
                                         </FlexLayout>
                                         <svgimage:SvgCachedImage Source="resource://dcbel.Mobile.Resources.alarmicon.svg" HeightRequest="25" FlexLayout.Basis="15%"/>
                                     </FlexLayout>
                                 </FlexLayout>
                             </ViewCell>
                         </DataTemplate>
                     </ListView.ItemTemplate>
                 </ListView>
             </AbsoluteLayout>
             <FlexLayout x:Name="Commands" Direction="Column" AlignItems="Center" JustifyContent="End" FlexLayout.Basis="15%">
                 <FlexLayout Direction="Row" JustifyContent="Center" HeightRequest="48">
                     <Button x:Name="ScheduleNewCharge" Text="{x:Static resources:AppResources.NewCharge}" TextTransform="None" BackgroundColor="#323F4B" TextColor="{AppThemeBinding Light=#FFFFFF, Dark=White}" FlexLayout.Basis="85%" />
                 </FlexLayout>
             </FlexLayout>
             <FlexLayout Direction="Column" FlexLayout.Basis="0%">
                 <control:CustomDatePicker x:Name="DatePicker" DoneButtonText="{x:Static resources:AppResources.Next}" CancelButtonText="{x:Static resources:AppResources.Cancel}" TitleText="{x:Static resources:AppResources.NewCharge}" IsEnabled="False" ios:DatePicker.UpdateMode="WhenFinished" />
             </FlexLayout>
         </FlexLayout>
     </ContentPage.Content>
 </local:ViewBase>
· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Please enable your custom datepicker .

85086-capture.png


0 Votes 0 ·
capture.png (11.0 KiB)

Removed that which therefore enables the date picker and yet it still doesn't fire the events

0 Votes 0 ·

Could you remove all the layout just leave custom datapicker alone to see if problem persists ?

0 Votes 0 ·
Show more comments