如何定义和使用 IOn[X]SetListenerImplementor
How do I define and use IOn[X]SetListenerImplementor
我正在阅读 Xamarin 的源代码并遇到了这两个对话框:TimePickerDialog
and DatePickerDialog
。
阅读这些内容时,我发现有一个正在实例化的对象,我无法在其他任何地方找到它。
我想知道这些监听器实现者的目的是什么,以及如何真正着手创建我自己的(或者我是否需要自己创建)。我的目标是创建一些自定义 PickerDialog
,所以我正在检查它们是如何实现的。
这是TimePickerDialog
:
using System;
using System.Collections.Generic;
using Android.Runtime;
namespace Android.App {
public partial class TimePickerDialog {
public TimePickerDialog (Android.Content.Context context, EventHandler<TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView)
// ** The IOnTimeSetListenerImplementor here **
: this (context, new IOnTimeSetListenerImplementor () { Handler = callBack }, hourOfDay, minute, is24HourView) {}
public TimePickerDialog (Android.Content.Context context, int theme, EventHandler<TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView)
: this (context, theme, new IOnTimeSetListenerImplementor () { Handler = callBack }, hourOfDay, minute, is24HourView) {}
}
}
这是DatePickerDialog
:
using System;
using System.Collections.Generic;
using Android.Runtime;
namespace Android.App {
public partial class DatePickerDialog {
public partial class DateSetEventArgs {
public DateTime Date {
get { return new DateTime (Year, Month + 1, DayOfMonth); }
}
#if ANDROID_24
[Obsolete ("This parameter in DateTimePickerDialog constructor is removed in Android API, so it will vanish from this automatically generated type too.")]
public int MonthOfYear {
get { return Month; }
}
#else
public int Month {
get { return monthOfYear; }
}
#endif
}
public DatePickerDialog (Android.Content.Context context, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth)
// ** The IOnDateSetListenerImplementor here **
: this (context, new IOnDateSetListenerImplementor () { Handler = callBack }, year, monthOfYear, dayOfMonth) {}
public DatePickerDialog (Android.Content.Context context, int theme, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth)
: this (context, theme, new IOnDateSetListenerImplementor () { Handler = callBack }, year, monthOfYear, dayOfMonth) {}
public void UpdateDate (DateTime date)
{
UpdateDate (date.Year, date.Month - 1, date.Day);
}
}
}
额外问题:为什么这两个 类 定义为部分 类?我无法在此回购中的其他任何地方找到其他部分。可能是我搜索的不对,也可能是为了以后的扩展?
感谢您的帮助!
我在搜索 Android.App.DatePickerDialog
的元数据时发现了以下内容(通过 Right-Clicking 在 Visual Studio 中输入 class 名称并选择转到定义很容易):
#region Assembly Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
// C:\Program Files (x86)\Microsoft Visual Studio19\Community\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v11.0\Mono.Android.dll
#endregion
#nullable enable
using Android.Content;
using Android.Runtime;
using Android.Widget;
using Java.Interop;
using System;
using System.ComponentModel;
using System.Diagnostics;
namespace Android.App
{
[Register("android/app/DatePickerDialog", DoNotGenerateAcw = true)]
public class DatePickerDialog : AlertDialog, IDialogInterfaceOnClickListener, IJavaObject, IDisposable, IJavaPeerable, DatePicker.IOnDateChangedListener
{
[Register(".ctor", "(Landroid/content/Context;)V", "", ApiSince = 24)]
public DatePickerDialog(Context context);
[Register(".ctor", "(Landroid/content/Context;I)V", "", ApiSince = 24)]
public DatePickerDialog(Context context, int themeResId);
public DatePickerDialog(Context context, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth);
[Register(".ctor", "(Landroid/content/Context;Landroid/app/DatePickerDialog$OnDateSetListener;III)V", "")]
public DatePickerDialog(Context context, IOnDateSetListener? listener, int year, int month, int dayOfMonth);
public DatePickerDialog(Context context, int theme, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth);
[Register(".ctor", "(Landroid/content/Context;ILandroid/app/DatePickerDialog$OnDateSetListener;III)V", "")]
public DatePickerDialog(Context context, int themeResId, IOnDateSetListener? listener, int year, int monthOfYear, int dayOfMonth);
protected DatePickerDialog(IntPtr javaReference, JniHandleOwnership transfer);
public virtual DatePicker DatePicker { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override JniPeerMembers JniPeerMembers { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override Type ThresholdType { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override IntPtr ThresholdClass { get; }
public event EventHandler<DateSetEventArgs> DateSet;
[Register("onClick", "(Landroid/content/DialogInterface;I)V", "GetOnClick_Landroid_content_DialogInterface_IHandler")]
public virtual void OnClick(IDialogInterface dialog, int which);
[Register("onDateChanged", "(Landroid/widget/DatePicker;III)V", "GetOnDateChanged_Landroid_widget_DatePicker_IIIHandler")]
public virtual void OnDateChanged(DatePicker view, int year, int month, int dayOfMonth);
[Register("setOnDateSetListener", "(Landroid/app/DatePickerDialog$OnDateSetListener;)V", "GetSetOnDateSetListener_Landroid_app_DatePickerDialog_OnDateSetListener_Handler", ApiSince = 24)]
public virtual void SetOnDateSetListener(IOnDateSetListener? listener);
public void UpdateDate(DateTime date);
[Register("updateDate", "(III)V", "GetUpdateDate_IIIHandler")]
public virtual void UpdateDate(int year, int month, int dayOfMonth);
[Register("android/app/DatePickerDialog$OnDateSetListener", "", "Android.App.DatePickerDialog/IOnDateSetListenerInvoker")]
public interface IOnDateSetListener : IJavaObject, IDisposable, IJavaPeerable
{
[Register("onDateSet", "(Landroid/widget/DatePicker;III)V", "GetOnDateSet_Landroid_widget_DatePicker_IIIHandler:Android.App.DatePickerDialog/IOnDateSetListenerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
void OnDateSet(DatePicker? view, int year, int month, int dayOfMonth);
}
public class DateSetEventArgs : EventArgs
{
public DateSetEventArgs(int year, int month, int dayOfMonth);
public DateTime Date { get; }
[Obsolete("This parameter in DateTimePickerDialog constructor is removed in Android API, so it will vanish from this automatically generated type too.")]
public int MonthOfYear { get; }
public int Year { get; }
public int Month { get; }
public int DayOfMonth { get; }
}
}
}
我看到 IOnDateSetListener
接口是在 class 中定义的。我还注意到 class 不再标记为 partial
。
然后我也找到了 DatePickerDialog+IOnDateSetListener.xml
:
<Type Name="DatePickerDialog+IOnDateSetListener" FullName="Android.App.DatePickerDialog+IOnDateSetListener">
<TypeSignature Language="C#" Value="public interface DatePickerDialog.IOnDateSetListener : Android.Runtime.IJavaObject, IDisposable, Java.Interop.IJavaPeerable" />
<TypeSignature Language="ILAsm" Value=".class nested public interface auto ansi abstract DatePickerDialog/IOnDateSetListener implements class Android.Runtime.IJavaObject, class Java.Interop.IJavaPeerable, class System.IDisposable" />
<TypeSignature Language="DocId" Value="T:Android.App.DatePickerDialog.IOnDateSetListener" />
<TypeSignature Language="F#" Value="type DatePickerDialog.IOnDateSetListener = interface
 interface IJavaObject
 interface IDisposable
 interface IJavaPeerable" />
...
<AttributeName Language="C#">[Android.Runtime.Register("android/app/DatePickerDialog$OnDateSetListener", "", "Android.App.DatePickerDialog/IOnDateSetListenerInvoker")]</AttributeName>
<AttributeName Language="F#">[<Android.Runtime.Register("android/app/DatePickerDialog$OnDateSetListener", "", "Android.App.DatePickerDialog/IOnDateSetListenerInvoker")>]</AttributeName>
...
<a href="https://developer.android.com/reference/android/app/DatePickerDialog$OnDateSetListener" title="Reference documentation">Android platform documentation</a>
...
<Type Name="DatePickerDialog" FullName="Android.App.DatePickerDialog">
<TypeSignature Language="C#" Value="public class DatePickerDialog : Android.App.AlertDialog, Android.Content.IDialogInterfaceOnClickListener, Android.Widget.DatePicker.IOnDateChangedListener, IDisposable, Java.Interop.IJavaPeerable" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DatePickerDialog extends Android.App.AlertDialog implements class Android.Content.IDialogInterfaceOnClickListener, class Android.Runtime.IJavaObject, class Android.Widget.DatePicker/IOnDateChangedListener, class Java.Interop.IJavaPeerable, class System.IDisposable" />
<TypeSignature Language="DocId" Value="T:Android.App.DatePickerDialog" />
<TypeSignature Language="F#" Value="type DatePickerDialog = class
 inherit AlertDialog
 interface IDialogInterfaceOnClickListener
 interface IJavaObject
 interface IDisposable
 interface IJavaPeerable
 interface DatePicker.IOnDateChangedListener" />
<AssemblyInfo>
<AssemblyName>Mono.Android</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>Android.App.AlertDialog</BaseTypeName>
</Base>
<Interfaces>
<Interface>
<InterfaceName>Android.Content.IDialogInterfaceOnClickListener</InterfaceName>
</Interface>
<Interface>
<InterfaceName>Android.Runtime.IJavaObject</InterfaceName>
</Interface>
<Interface>
<InterfaceName>Android.Widget.DatePicker+IOnDateChangedListener</InterfaceName>
</Interface>
...
上述两个文件都提到了它。我最好的猜测是,有些构建事件使用此信息来构建 cross-language 方法并将它们注入部分 classes。 c# DatePickerDialog
(来自元数据)可能是编译时事件将问题中提到的 DatePickerDialog
与构建 Xamarin 库时包含在 XML 文件中的信息合并的结果并打包。
侦听器接口似乎特定于 DatePicker
和 TimePicker
的行为,并且似乎并非在所有情况下都是必需的。
无需尝试复制该行为,创建一个扩展 AlertDialog
and calling the SetView
方法的自定义对话框可能就足够了。
编辑:
Xamarin Community Toolkit 中还包含一个 Popup
class,这使得制作自定义对话框(如问题中引用的对话框)变得非常容易。请参阅文档 here。
我正在阅读 Xamarin 的源代码并遇到了这两个对话框:TimePickerDialog
and DatePickerDialog
。
阅读这些内容时,我发现有一个正在实例化的对象,我无法在其他任何地方找到它。
我想知道这些监听器实现者的目的是什么,以及如何真正着手创建我自己的(或者我是否需要自己创建)。我的目标是创建一些自定义 PickerDialog
,所以我正在检查它们是如何实现的。
这是TimePickerDialog
:
using System;
using System.Collections.Generic;
using Android.Runtime;
namespace Android.App {
public partial class TimePickerDialog {
public TimePickerDialog (Android.Content.Context context, EventHandler<TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView)
// ** The IOnTimeSetListenerImplementor here **
: this (context, new IOnTimeSetListenerImplementor () { Handler = callBack }, hourOfDay, minute, is24HourView) {}
public TimePickerDialog (Android.Content.Context context, int theme, EventHandler<TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView)
: this (context, theme, new IOnTimeSetListenerImplementor () { Handler = callBack }, hourOfDay, minute, is24HourView) {}
}
}
这是DatePickerDialog
:
using System;
using System.Collections.Generic;
using Android.Runtime;
namespace Android.App {
public partial class DatePickerDialog {
public partial class DateSetEventArgs {
public DateTime Date {
get { return new DateTime (Year, Month + 1, DayOfMonth); }
}
#if ANDROID_24
[Obsolete ("This parameter in DateTimePickerDialog constructor is removed in Android API, so it will vanish from this automatically generated type too.")]
public int MonthOfYear {
get { return Month; }
}
#else
public int Month {
get { return monthOfYear; }
}
#endif
}
public DatePickerDialog (Android.Content.Context context, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth)
// ** The IOnDateSetListenerImplementor here **
: this (context, new IOnDateSetListenerImplementor () { Handler = callBack }, year, monthOfYear, dayOfMonth) {}
public DatePickerDialog (Android.Content.Context context, int theme, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth)
: this (context, theme, new IOnDateSetListenerImplementor () { Handler = callBack }, year, monthOfYear, dayOfMonth) {}
public void UpdateDate (DateTime date)
{
UpdateDate (date.Year, date.Month - 1, date.Day);
}
}
}
额外问题:为什么这两个 类 定义为部分 类?我无法在此回购中的其他任何地方找到其他部分。可能是我搜索的不对,也可能是为了以后的扩展?
感谢您的帮助!
我在搜索 Android.App.DatePickerDialog
的元数据时发现了以下内容(通过 Right-Clicking 在 Visual Studio 中输入 class 名称并选择转到定义很容易):
#region Assembly Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=84e04ff9cfb79065
// C:\Program Files (x86)\Microsoft Visual Studio19\Community\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v11.0\Mono.Android.dll
#endregion
#nullable enable
using Android.Content;
using Android.Runtime;
using Android.Widget;
using Java.Interop;
using System;
using System.ComponentModel;
using System.Diagnostics;
namespace Android.App
{
[Register("android/app/DatePickerDialog", DoNotGenerateAcw = true)]
public class DatePickerDialog : AlertDialog, IDialogInterfaceOnClickListener, IJavaObject, IDisposable, IJavaPeerable, DatePicker.IOnDateChangedListener
{
[Register(".ctor", "(Landroid/content/Context;)V", "", ApiSince = 24)]
public DatePickerDialog(Context context);
[Register(".ctor", "(Landroid/content/Context;I)V", "", ApiSince = 24)]
public DatePickerDialog(Context context, int themeResId);
public DatePickerDialog(Context context, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth);
[Register(".ctor", "(Landroid/content/Context;Landroid/app/DatePickerDialog$OnDateSetListener;III)V", "")]
public DatePickerDialog(Context context, IOnDateSetListener? listener, int year, int month, int dayOfMonth);
public DatePickerDialog(Context context, int theme, EventHandler<DateSetEventArgs> callBack, int year, int monthOfYear, int dayOfMonth);
[Register(".ctor", "(Landroid/content/Context;ILandroid/app/DatePickerDialog$OnDateSetListener;III)V", "")]
public DatePickerDialog(Context context, int themeResId, IOnDateSetListener? listener, int year, int monthOfYear, int dayOfMonth);
protected DatePickerDialog(IntPtr javaReference, JniHandleOwnership transfer);
public virtual DatePicker DatePicker { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override JniPeerMembers JniPeerMembers { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override Type ThresholdType { get; }
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[EditorBrowsable(EditorBrowsableState.Never)]
protected override IntPtr ThresholdClass { get; }
public event EventHandler<DateSetEventArgs> DateSet;
[Register("onClick", "(Landroid/content/DialogInterface;I)V", "GetOnClick_Landroid_content_DialogInterface_IHandler")]
public virtual void OnClick(IDialogInterface dialog, int which);
[Register("onDateChanged", "(Landroid/widget/DatePicker;III)V", "GetOnDateChanged_Landroid_widget_DatePicker_IIIHandler")]
public virtual void OnDateChanged(DatePicker view, int year, int month, int dayOfMonth);
[Register("setOnDateSetListener", "(Landroid/app/DatePickerDialog$OnDateSetListener;)V", "GetSetOnDateSetListener_Landroid_app_DatePickerDialog_OnDateSetListener_Handler", ApiSince = 24)]
public virtual void SetOnDateSetListener(IOnDateSetListener? listener);
public void UpdateDate(DateTime date);
[Register("updateDate", "(III)V", "GetUpdateDate_IIIHandler")]
public virtual void UpdateDate(int year, int month, int dayOfMonth);
[Register("android/app/DatePickerDialog$OnDateSetListener", "", "Android.App.DatePickerDialog/IOnDateSetListenerInvoker")]
public interface IOnDateSetListener : IJavaObject, IDisposable, IJavaPeerable
{
[Register("onDateSet", "(Landroid/widget/DatePicker;III)V", "GetOnDateSet_Landroid_widget_DatePicker_IIIHandler:Android.App.DatePickerDialog/IOnDateSetListenerInvoker, Mono.Android, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null")]
void OnDateSet(DatePicker? view, int year, int month, int dayOfMonth);
}
public class DateSetEventArgs : EventArgs
{
public DateSetEventArgs(int year, int month, int dayOfMonth);
public DateTime Date { get; }
[Obsolete("This parameter in DateTimePickerDialog constructor is removed in Android API, so it will vanish from this automatically generated type too.")]
public int MonthOfYear { get; }
public int Year { get; }
public int Month { get; }
public int DayOfMonth { get; }
}
}
}
我看到 IOnDateSetListener
接口是在 class 中定义的。我还注意到 class 不再标记为 partial
。
然后我也找到了 DatePickerDialog+IOnDateSetListener.xml
:
<Type Name="DatePickerDialog+IOnDateSetListener" FullName="Android.App.DatePickerDialog+IOnDateSetListener">
<TypeSignature Language="C#" Value="public interface DatePickerDialog.IOnDateSetListener : Android.Runtime.IJavaObject, IDisposable, Java.Interop.IJavaPeerable" />
<TypeSignature Language="ILAsm" Value=".class nested public interface auto ansi abstract DatePickerDialog/IOnDateSetListener implements class Android.Runtime.IJavaObject, class Java.Interop.IJavaPeerable, class System.IDisposable" />
<TypeSignature Language="DocId" Value="T:Android.App.DatePickerDialog.IOnDateSetListener" />
<TypeSignature Language="F#" Value="type DatePickerDialog.IOnDateSetListener = interface
 interface IJavaObject
 interface IDisposable
 interface IJavaPeerable" />
...
<AttributeName Language="C#">[Android.Runtime.Register("android/app/DatePickerDialog$OnDateSetListener", "", "Android.App.DatePickerDialog/IOnDateSetListenerInvoker")]</AttributeName>
<AttributeName Language="F#">[<Android.Runtime.Register("android/app/DatePickerDialog$OnDateSetListener", "", "Android.App.DatePickerDialog/IOnDateSetListenerInvoker")>]</AttributeName>
...
<a href="https://developer.android.com/reference/android/app/DatePickerDialog$OnDateSetListener" title="Reference documentation">Android platform documentation</a>
...
<Type Name="DatePickerDialog" FullName="Android.App.DatePickerDialog">
<TypeSignature Language="C#" Value="public class DatePickerDialog : Android.App.AlertDialog, Android.Content.IDialogInterfaceOnClickListener, Android.Widget.DatePicker.IOnDateChangedListener, IDisposable, Java.Interop.IJavaPeerable" />
<TypeSignature Language="ILAsm" Value=".class public auto ansi beforefieldinit DatePickerDialog extends Android.App.AlertDialog implements class Android.Content.IDialogInterfaceOnClickListener, class Android.Runtime.IJavaObject, class Android.Widget.DatePicker/IOnDateChangedListener, class Java.Interop.IJavaPeerable, class System.IDisposable" />
<TypeSignature Language="DocId" Value="T:Android.App.DatePickerDialog" />
<TypeSignature Language="F#" Value="type DatePickerDialog = class
 inherit AlertDialog
 interface IDialogInterfaceOnClickListener
 interface IJavaObject
 interface IDisposable
 interface IJavaPeerable
 interface DatePicker.IOnDateChangedListener" />
<AssemblyInfo>
<AssemblyName>Mono.Android</AssemblyName>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
</AssemblyInfo>
<Base>
<BaseTypeName>Android.App.AlertDialog</BaseTypeName>
</Base>
<Interfaces>
<Interface>
<InterfaceName>Android.Content.IDialogInterfaceOnClickListener</InterfaceName>
</Interface>
<Interface>
<InterfaceName>Android.Runtime.IJavaObject</InterfaceName>
</Interface>
<Interface>
<InterfaceName>Android.Widget.DatePicker+IOnDateChangedListener</InterfaceName>
</Interface>
...
上述两个文件都提到了它。我最好的猜测是,有些构建事件使用此信息来构建 cross-language 方法并将它们注入部分 classes。 c# DatePickerDialog
(来自元数据)可能是编译时事件将问题中提到的 DatePickerDialog
与构建 Xamarin 库时包含在 XML 文件中的信息合并的结果并打包。
侦听器接口似乎特定于 DatePicker
和 TimePicker
的行为,并且似乎并非在所有情况下都是必需的。
无需尝试复制该行为,创建一个扩展 AlertDialog
and calling the SetView
方法的自定义对话框可能就足够了。
编辑:
Xamarin Community Toolkit 中还包含一个 Popup
class,这使得制作自定义对话框(如问题中引用的对话框)变得非常容易。请参阅文档 here。