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