如何为自定义控件创建事件

时间:2016-04-19 09:33:16

标签: c# xamarin xamarin.forms

我创建了一个带有图像,2个标签和一个按钮的自定义控件(列表)。我想调用自定义控件的按钮单击。我的整个控制权也将有一个单独的事件。 enter image description here

这是我的usercontrol tamplate代码:

namespace __
{
    public class SelectMultipleBasePage<T> : ContentPage
    {

        public class WrappedSelection<T> : INotifyPropertyChanged
        {
            public T Item { get; set; }
            bool isSelected = false;
            public bool IsSelected
            {
                get
                {
                    return isSelected;
                }
                set
                {
                    if (isSelected != value)
                    {
                        isSelected = value;
                        PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
                        //                      PropertyChanged (this, new PropertyChangedEventArgs (nameof (IsSelected))); // C# 6
                    }
                }
            }
            public event PropertyChangedEventHandler PropertyChanged = delegate { };
        }
        public class BackGroundColorConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (value is bool)
                {
                    if ((bool)value)
                    {
                        return Color.FromHex("#DEE4EA");
                    }
                    else
                    {
                        return Color.White;
                    }
                }
                else
                {
                    return Color.White;
                }
            }

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }

        }

        public class WrappedItemSelectionTemplate : ViewCell
        {
             static int i=0; // don't forget to make it static 
            public WrappedItemSelectionTemplate()
                : base()
             {

                 var items = RecordingListPage.items;
                 Grid objGrid = new Grid();
                 objGrid.RowDefinitions.Add(new RowDefinition
                 {
                     Height = new GridLength(1, GridUnitType.Star)
                 });
                 objGrid.ColumnDefinitions.Add(new ColumnDefinition
                 {
                     Width = new GridLength(75, GridUnitType.Absolute),
                 });
                 objGrid.ColumnDefinitions.Add(new ColumnDefinition
                 {
                     Width = new GridLength(1, GridUnitType.Star)
                 });
                 objGrid.ColumnDefinitions.Add(new ColumnDefinition
                 {
                     Width = new GridLength(75, GridUnitType.Absolute),
                 });

                 // Column 1:-
                 Image objImage = new Image();
                 objImage.SetBinding(Image.SourceProperty, new Binding("Item.Image"));
                 objGrid.Children.Add(objImage, 0, 0);
                 // Column 2:-
                 StackLayout objStackLayoutCol2 = new StackLayout();
                 objGrid.Children.Add(objStackLayoutCol2, 1, 0);

                 Label name = new Label()
                 {
                     Text = "Name",
                     Style = (Style)Application.Current.Resources["LabelStyle"],
                 };
                 Label date = new Label()
                 {
                     Text = "Date",
                     Style = (Style)Application.Current.Resources["LabelStyleTiny"]
                 };
                 name.SetBinding(Label.TextProperty, new Binding("Item.Name"));
                 date.SetBinding(Label.TextProperty, new Binding("Item.Date"));
                 objStackLayoutCol2.Children.Add(name);
                 objStackLayoutCol2.Children.Add(date);
                 objStackLayoutCol2.Padding = new Thickness(10);

                 Label objImageView = new Label();
                 objImageView.Text = FontAwesome.FAPencilSquareO;
                 objImageView.FontSize = 35;
                 objImageView.VerticalOptions = LayoutOptions.CenterAndExpand;
                 objImageView.HorizontalOptions = LayoutOptions.CenterAndExpand;
                 objImageView.TextColor = Color.Black;

                 StackLayout stv = new StackLayout();
                 stv.Children.Add(objImageView);
                 stv.Padding = new Thickness(10);
                 stv.HorizontalOptions = LayoutOptions.Center;
                 stv.VerticalOptions = LayoutOptions.Center;

                 objImageView.StyleId = items[i].Id.ToString();
                 i++;
                 if (i == items.Count)
                 {
                     i = 0;
                 }

                 var tapGestureRecognizer = new TapGestureRecognizer();
                  tapGestureRecognizer.Tapped += OnImageBtnTapped;
                 objImageView.GestureRecognizers.Add(tapGestureRecognizer);

                 objGrid.Children.Add(stv, 2, 0);

                 var moreAction = new MenuItem { Text = "More" };

                 moreAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
                 moreAction.Clicked += (sender, e) =>
                 {
                     var mi = ((MenuItem)sender);
                     //Debug.WriteLine("More Context Action clicked: " + mi.CommandParameter);
                 };

                 var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
                 deleteAction.Icon = Device.OnPlatform("Icons/cancel.png", "cancel.png", "Images/cancel.png");
                 deleteAction.SetBinding(MenuItem.CommandParameterProperty, new Binding("."));
                 deleteAction.Clicked += (sender, e) =>
                 {
                     var mi = ((MenuItem)sender);
                     //Debug.WriteLine("Delete Context Action clicked: " + mi.CommandParameter);
                 };

                 //
                 // add context actions to the cell
                 //
                 ContextActions.Add(moreAction);
                 ContextActions.Add(deleteAction);
                 //objGrid.Padding = new Thickness(10);

                 StackLayout st = new StackLayout();
                 st.Children.Add(objGrid);
                 st.Children.Add(new BoxView() { Color = Color.FromHex("#A4B3C1"), WidthRequest = 100, HeightRequest = 1 });


                 View = st;


             }

            private void OnImageBtnTapped(object sender, EventArgs e)
            {
                var tappedImage = (Label)sender;
                var ImageId = Convert.ToInt32(tappedImage.StyleId);
                Application.Current.Properties["ItemId"] = ImageId;
                MessagingCenter.Send(new RedirectClass.OpenRecordingDetails(), RedirectClass.OpenRecordingDetails.Key);
            }

        }
        public static List<WrappedSelection<T>> WrappedItems = new List<WrappedSelection<T>>();
        public SelectMultipleBasePage(List<T> items)
        {
            WrappedItems = items.Select(item => new WrappedSelection<T>() { Item = item, IsSelected = false }).ToList();
            ListView mainList = new ListView()
            {
                ItemsSource = WrappedItems,
                ItemTemplate = new DataTemplate(typeof(WrappedItemSelectionTemplate)),
            };

            mainList.ItemSelected += (sender, e) =>
            {
                if (e.SelectedItem == null) return;
                var o = (WrappedSelection<T>)e.SelectedItem;
                o.IsSelected = !o.IsSelected;
                ((ListView)sender).SelectedItem = null; //de-select
            };
            Content = mainList;
            mainList.HasUnevenRows = true;


            if (Device.OS == TargetPlatform.WinPhone)
            {   // fix issue where rows are badly sized (as tall as the screen) on WinPhone8.1
                mainList.RowHeight = 40;
                // also need icons for Windows app bar (other platforms can just use text)
                ToolbarItems.Add(new ToolbarItem("All", "check.png", SelectAll, ToolbarItemOrder.Primary));
                ToolbarItems.Add(new ToolbarItem("None", "cancel.png", SelectNone, ToolbarItemOrder.Primary));
            }
            else
            {
                ToolbarItems.Add(new ToolbarItem("All", null, SelectAll, ToolbarItemOrder.Primary));
                ToolbarItems.Add(new ToolbarItem("None", null, SelectNone, ToolbarItemOrder.Primary));
            }
        }
        void SelectAll()
        {
            foreach (var wi in WrappedItems)
            {
                wi.IsSelected = true;
            }
        }
        void SelectNone()
        {
            foreach (var wi in WrappedItems)
            {
                wi.IsSelected = false;
            }
        }
        public static List<T> GetSelection()
        {
            return WrappedItems.Where(item => item.IsSelected).Select(wrappedItem => wrappedItem.Item).ToList();
        }
    }
}

我有一个事件OnImageBtnTapped,我想从我的内容页面访问它。我怎么能这样做?

修改

感谢@Jason,我设法在使用该控件的代码中获取事件单击功能。

在自定义控件类中:

private void OnImageBtnTapped(object sender, EventArgs e)
{
   if (OnImageSelected != null) 
   {
        OnImageSelected(sender,e);
   }
}

在使用控件的代码中,

SelectMultipleBasePage<ListItems>.OnImageSelected += ListPage_OnImageSelected;

void ListPage_OnImageSelected(object sender, EventArgs e)
{

    var tappedImage = (Label)sender;
    var ImageId = Convert.ToInt32(tappedImage.StyleId);

    Application.Current.Properties["ItemId"] = ImageId;

    MessagingCenter.Send(new RedirectClass.OpenRecordingDetails(), RedirectClass.OpenRecordingDetails.Key);
}

2 个答案:

答案 0 :(得分:3)

这与为任何C#代码创建自定义事件没有什么不同

首先,在您的班级中创建一个公共事件和处理程序:

// note: you may want to create your own ImageEventArgs class that inherits from EventArgs
public delegate void ImageSelectedHandler(object sender, EventArgs e);
public event ImageSelectedHandler OnImageSelected;

接下来,在控件内部,您可以调用处理程序(如果存在)

private void OnImageBtnTapped(object sender, EventArgs e)
{
  var tappedImage = (Label)sender;
  var ImageId = Convert.ToInt32(tappedImage.StyleId);
  Application.Current.Properties["ItemId"] = ImageId;

  MessagingCenter.Send(new RedirectClass.OpenRecordingDetails(), RedirectClass.OpenRecordingDetails.Key);

  // check if a handler is assigned
  if (OnImageSelected != null) {
    OnImageSelected(this,new EventArgs(...));
  }
}

最后,在使用该控件的代码中,只需像通常那样定义一个事件处理程序

myControl.OnImageSelected += delegate {
  // handler logic goes here
};

答案 1 :(得分:0)

您可以将处理程序从父级移交给子级。然后它不涉及静态事件处理程序。您只需向react-native run-android JS server already running. Building and installing the app on the device (cd android && ./gradlew installDebug... :app:preBuild UP-TO-DATE :app:preDebugBuild UP-TO-DATE :app:checkDebugManifest :app:preReleaseBuild UP-TO-DATE :react-native-camera:compileLint :react-native-camera:copyReleaseLint UP-TO-DATE :react-native-camera:preBuild UP-TO-DATE :react-native-camera:preReleaseBuild UP-TO-DATE :react-native-camera:checkReleaseManifest :react-native-camera:preDebugAndroidTestBuild UP-TO-DATE :react-native-camera:preDebugBuild UP-TO-DATE :react-native-camera:preDebugUnitTestBuild UP-TO-DATE :react-native-camera:preReleaseUnitTestBuild UP-TO-DATE :react-native-camera:prepareComAndroidSupportAppcompatV72301Library UP-TO-DATE :react-native-camera:prepareComAndroidSupportRecyclerviewV72301Library UP-TO-DATE :react-native-camera:prepareComAndroidSupportSupportV42301Library UP-TO-DATE :react-native-camera:prepareComFacebookFrescoDrawee081Library UP-TO-DATE :react-native-camera:prepareComFacebookFrescoFbcore081Library UP-TO-DATE :react-native-camera:prepareComFacebookFrescoFresco081Library UP-TO-DATE :react-native-camera:prepareComFacebookFrescoImagepipeline081Library UP-TO-DATE :react-native-camera:prepareComFacebookFrescoImagepipelineOkhttp081Library UP-TO-DATE :react-native-camera:prepareComFacebookReactReactNative0191Library UP-TO-DATE :react-native-camera:prepareOrgWebkitAndroidJscR174650Library UP-TO-DATE :react-native-camera:prepareReleaseDependencies :react-native-camera:compileReleaseAidl UP-TO-DATE :react-native-camera:compileReleaseRenderscript UP-TO-DATE :react-native-camera:generateReleaseBuildConfig UP-TO-DATE :react-native-camera:generateReleaseAssets UP-TO-DATE :react-native-camera:mergeReleaseAssets UP-TO-DATE :react-native-camera:generateReleaseResValues UP-TO-DATE :react-native-camera:generateReleaseResources UP-TO-DATE :react-native-camera:mergeReleaseResources UP-TO-DATE :react-native-camera:processReleaseManifest UP-TO-DATE :react-native-camera:processReleaseResources UP-TO-DATE :react-native-camera:generateReleaseSources UP-TO-DATE :react-native-camera:processReleaseJavaRes UP-TO-DATE :react-native-camera:compileReleaseJavaWithJavac UP-TO-DATE :react-native-camera:extractReleaseAnnotations UP-TO-DATE :react-native-camera:mergeReleaseProguardFiles UP-TO-DATE :react-native-camera:packageReleaseJar UP-TO-DATE :react-native-camera:compileReleaseNdk UP-TO-DATE :react-native-camera:packageReleaseJniLibs UP-TO-DATE :react-native-camera:packageReleaseLocalJar UP-TO-DATE :react-native-camera:packageReleaseRenderscript UP-TO-DATE :react-native-camera:packageReleaseResources UP-TO-DATE :react-native-camera:bundleRelease UP-TO-DATE :react-native-hockeyapp:compileLint :react-native-hockeyapp:copyReleaseLint UP-TO-DATE :react-native-hockeyapp:preBuild UP-TO-DATE :react-native-hockeyapp:preReleaseBuild UP-TO-DATE :react-native-hockeyapp:checkReleaseManifest :react-native-hockeyapp:preDebugAndroidTestBuild UP-TO-DATE :react-native-hockeyapp:preDebugBuild UP-TO-DATE :react-native-hockeyapp:preDebugUnitTestBuild UP-TO-DATE :react-native-hockeyapp:preReleaseUnitTestBuild UP-TO-DATE :react-native-hockeyapp:prepareComAndroidSupportAppcompatV72301Library UP-TO-DATE :react-native-hockeyapp:prepareComAndroidSupportRecyclerviewV72301Library UP-TO-DATE :react-native-hockeyapp:prepareComAndroidSupportSupportV42301Library UP-TO-DATE :react-native-hockeyapp:prepareComFacebookFrescoDrawee061Library UP-TO-DATE :react-native-hockeyapp:prepareComFacebookFrescoFbcore061Library UP-TO-DATE :react-native-hockeyapp:prepareComFacebookFrescoFresco061Library UP-TO-DATE :react-native-hockeyapp:prepareComFacebookFrescoImagepipeline061Library UP-TO-DATE :react-native-hockeyapp:prepareComFacebookFrescoImagepipelineOkhttp061Library UP-TO-DATE :react-native-hockeyapp:prepareComFacebookReactReactNative0140Library UP-TO-DATE :react-native-hockeyapp:prepareNetHockeyappAndroidHockeySDK370Library UP-TO-DATE :react-native-hockeyapp:prepareOrgWebkitAndroidJscR174650Library UP-TO-DATE :react-native-hockeyapp:prepareReleaseDependencies :react-native-hockeyapp:compileReleaseAidl UP-TO-DATE :react-native-hockeyapp:compileReleaseRenderscript UP-TO-DATE :react-native-hockeyapp:generateReleaseBuildConfig UP-TO-DATE :react-native-hockeyapp:generateReleaseAssets UP-TO-DATE :react-native-hockeyapp:mergeReleaseAssets UP-TO-DATE :react-native-hockeyapp:generateReleaseResValues UP-TO-DATE :react-native-hockeyapp:generateReleaseResources UP-TO-DATE :react-native-hockeyapp:mergeReleaseResources UP-TO-DATE :react-native-hockeyapp:processReleaseManifest UP-TO-DATE :react-native-hockeyapp:processReleaseResources UP-TO-DATE :react-native-hockeyapp:generateReleaseSources UP-TO-DATE :react-native-hockeyapp:processReleaseJavaRes UP-TO-DATE :react-native-hockeyapp:compileReleaseJavaWithJavac UP-TO-DATE :react-native-hockeyapp:extractReleaseAnnotations UP-TO-DATE :react-native-hockeyapp:mergeReleaseProguardFiles UP-TO-DATE :react-native-hockeyapp:packageReleaseJar UP-TO-DATE :react-native-hockeyapp:compileReleaseNdk UP-TO-DATE :react-native-hockeyapp:packageReleaseJniLibs UP-TO-DATE :react-native-hockeyapp:packageReleaseLocalJar UP-TO-DATE :react-native-hockeyapp:packageReleaseRenderscript UP-TO-DATE :react-native-hockeyapp:packageReleaseResources UP-TO-DATE :react-native-hockeyapp:bundleRelease UP-TO-DATE :app:prepareComAndroidSupportAppcompatV72301Library UP-TO-DATE :app:prepareComAndroidSupportRecyclerviewV72301Library UP-TO-DATE :app:prepareComAndroidSupportSupportV42301Library UP-TO-DATE :app:prepareComFacebookFrescoDrawee081Library UP-TO-DATE :app:prepareComFacebookFrescoFbcore081Library UP-TO-DATE :app:prepareComFacebookFrescoFresco081Library UP-TO-DATE :app:prepareComFacebookFrescoImagepipeline081Library UP-TO-DATE :app:prepareComFacebookFrescoImagepipelineOkhttp081Library UP-TO-DATE :app:prepareComFacebookReactReactNative0230Library UP-TO-DATE :app:prepareNetHockeyappAndroidHockeySDK370Library UP-TO-DATE :app:prepareOrgWebkitAndroidJscR174650Library UP-TO-DATE :app:prepareSikayetvarReactNativeCameraUnspecifiedLibrary UP-TO-DATE :app:prepareSikayetvarReactNativeHockeyappUnspecifiedLibrary UP-TO-DATE :app:prepareDebugDependencies :app:compileDebugAidl UP-TO-DATE :app:compileDebugRenderscript UP-TO-DATE :app:generateDebugBuildConfig UP-TO-DATE :app:generateDebugAssets UP-TO-DATE :app:mergeDebugAssets UP-TO-DATE :app:generateDebugResValues UP-TO-DATE :app:generateDebugResources UP-TO-DATE :app:mergeDebugResources UP-TO-DATE :app:bundleDebugJsAndAssets SKIPPED :app:processDebugManifest UP-TO-DATE :app:processDebugResources UP-TO-DATE :app:generateDebugSources UP-TO-DATE :app:processDebugJavaRes UP-TO-DATE :app:compileDebugJavaWithJavac UP-TO-DATE :app:compileDebugNdk UP-TO-DATE :app:compileDebugSources UP-TO-DATE :app:preDexDebug UP-TO-DATE :app:dexDebug UP-TO-DATE :app:validateDebugSigning :app:packageDebug UP-TO-DATE :app:zipalignDebug UP-TO-DATE :app:assembleDebug UP-TO-DATE :app:installDebug Installing APK 'app-debug.apk' on 'PREVIEW - Google Nexus 5X - 6.0.0 - API 23 - 1080x1920 - 6.0' Installed on 1 device. BUILD SUCCESSFUL Total time: 6.342 secs Starting the app on 192.168.56.101:5555 (/home/myuser/Android/Sdk/platform-tools/adb -s 192.168.56.101:5555 shell am start -n com.myApp/.MainActivity)... Starting: Intent { cmp=com.myApp/.MainActivity } 添加参数,然后使用WrappedItemSelectionTemplate创建模板。

new DataTemplate(() => new WrappedItemSelectionTemplate(HandleImageSelected))