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

C# 如何为自定义控件创建事件,c#,xamarin,xamarin.forms,C#,Xamarin,Xamarin.forms,我创建了一个带有图像、两个标签和一个按钮的自定义控件(列表)。我想调用自定义控件的按钮单击。我的整个控制也将有一个单独的事件 以下是我的usercontrol tamplate代码: namespace __ { public class SelectMultipleBasePage<T> : ContentPage { public class WrappedSelection<T> : INotifyPropertyChanged

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

以下是我的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();
        }
    }
}
在使用控件的代码中

selectmultiplebsepage.OnImageSelected+=ListPage\u OnImageSelected;
void ListPage_OnImageSelected(对象发送方,事件参数e)
{
var tappedImage=(标签)发送方;
var ImageId=Convert.ToInt32(tappedImage.StyleId);
Application.Current.Properties[“ItemId”]=ImageId;
MessagingCenter.Send(新建RedirectClass.OpenRecordingDetails(),RedirectClass.OpenRecordingDetails.Key);
}

这与为任何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
};

这与为任何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
};

您可以将处理程序从父级移交给子级。然后,它不涉及静态事件处理程序。您只需向
WrappedItemSelectionTemplate
添加一个参数,然后使用
newdataTemplate(()=>newwrappedItemSelectionTemplate(HandleImageSelected))
创建模板

public类选择multiplebasepage:ContentPage
{
公共委托无效ImageSelectedHandler(对象发送方,事件参数e);
公共事件ImageSelectedHandler OnImageSelected;
公共类WrappedItemSelectionTemplate:ViewCell
{
private readonly ImageSelectedHandler\u parentHandler;
公共WrappedItemSelectionTemplate(ImageSelectedHandler parentHandler)
:base()
{
_parentHandler=parentHandler;
// ...
视图=st;
}
私有void OnImagebtentaped(对象发送方,事件参数e)
{
//...
_调用(发送方,e);
}
}
public static List WrappedItems=new List();
公共选择多重分隔页(列表项)
{
WrappedItems=items.Select(item=>newwrappedselection(){item=item,IsSelected=false}).ToList();
ListView mainList=新建ListView()
{
ItemsSource=WrappedItems,
ItemTemplate=new DataTemplate(()=>new WrappedItemSelectionTemplate(HandleImageSelected)),
};
// ...
}
已选择private void HandleImages(对象发送方,事件参数e)
{
如果(OnImageSelected!=null)
{
所选图像(发送方,e);
}
}
}

您可以将处理程序从父级移交给子级。然后,它不涉及静态事件处理程序。您只需向
WrappedItemSelectionTemplate
添加一个参数,然后使用
newdataTemplate(()=>newwrappedItemSelectionTemplate(HandleImageSelected))
创建模板

public类选择multiplebasepage:ContentPage
{
公共委托无效ImageSelectedHandler(对象发送方,事件参数e);
公共事件ImageSelectedHandler OnImageSelected;
公共类WrappedItemSelectionTemplate:ViewCell
{
private readonly ImageSelectedHandler\u parentHandler;
公共WrappedItemSelectionTemplate(ImageSelectedHandler parentHandler)
:base()
{
_parentHandler=parentHandler;
// ...
视图=st;
}
私有void OnImagebtentaped(对象发送方,事件参数e)
{
//...
_调用(发送方,e);
}
}
public static List WrappedItems=new List();
公共选择多重分隔页(列表项)
{
WrappedItems=items.Select(item=>newwrappedselection(){item=item,IsSelected=false}).ToList();
ListView mainList=新建ListView()
{
ItemsSource=WrappedItems,
ItemTemplate=new DataTemplate(()=>new WrappedItemSelectionTemplate(HandleImageSelected)),
};
// ...
}
已选择private void HandleImages(对象发送方,事件参数e)
{
如果(OnImageSelected!=null)
{
所选图像(发送方,e);
}
}
}

它确实有效,但不知何故我无法定义这样的偶数句柄:
SelectMultipleBasePage multiPage=newselectmultiplebasepage(items);multiPage.OnImageSelected+=录制列表页面_OnImageSelected我想在不同的页面上使用此控件和事件。我该怎么做?它确实起作用了,但不知何故我无法定义这样的偶数句柄:
SelectMultipleBasePage multiPage=newselectmultiplebasepage(items);multiPage.OnImageSelected+=录制列表页面_OnImageSelected我想在不同的页面上使用此控件和事件。如何操作?如何访问使用控件的页面中的事件?
SelectMultipleBasePage multiPage=new SelectMultipleBasePage(items);multiPage.OnImageSelected+=录制列表页面_OnImageSelected不工作。错误:
Error 20 Member'AppName.selectMultipleBSepage.OnImageSelected'无法通过实例引用访问;用一个类型名来限定它,然后你在某个地方有一个
静态的
。是的,很抱歉,这是我这边的一个错误。但现在我可以访问该事件,但在加载页面时获取
System.NullReferenceException:Object reference未设置为对象的实例。我将调试以查看错误的来源。如何访问使用控件的页面中的事件?
SelectMultipleBasePage multiPage=new SelectMultipleBasePage(items);多通道