更新 : 2007 年 11 月
ASP.NET モバイル コントロールの ObjectList を使用すると、データの多機能なビューを提供できます。このコントロールは、データ ソースの 2 つのビューを表示します。1 つは、各項目の要約を表示するリスト ビューで、もう 1 つは、項目の詳細を表示するビューです。表示する各項目の一覧フィールドを明示的に定義することや、一覧フィールドをデータ ソースから自動的に生成することができます。既定では、コントロールはデータ ソース内部に出現する順序で、データ ソース内の各フィールドに対応するフィールドを生成します。自動的に生成された各フィールドの名前は、そのフィールドのタイトルとして使用されます。
ObjectList コントロールのデータを DataView または DataSet オブジェクトにバインドできます。ObjectList モバイル コントロールのデータを DataView オブジェクトにバインドするには、DataSource プロパティを設定し、DataBind メソッドを呼び出します。たとえば、Titles という名前のテーブルを持つ DataSet オブジェクトがある場合は、次のステートメントを使用してデータ バインディングを行うことができます。
myObjectList.DataSource = ds.Tables["Titles"].DefaultView;
myObjectList.DataBind();
また、DataSet オブジェクトに直接データをバインドするには、DataMember プロパティにこのテーブルの名前を設定します。次のサンプルは、上のサンプルと同じ意味になります。
myObjectList.DataSource = ds;
myObjectList.DataMember = "Titles";
myObjectList.DataBind();
項目のフィールドを、データ項目のいくつかのプロパティで構成される値に設定することもできます。これを行うには、ObjectList コントロールの ItemDataBind イベントをオーバーライドし、プログラムでフィールドを設定します。次のサンプルでは、Summary フィールドを書籍の書名と価格を組み合わせたものに設定します。
private void ObjectList_OnItemDataBind(Object sender,
ObjectListDataBindEventArgs e)
{
e.ListItem["Summary"] = String.Format( String.Format ("{0} – {1}",
DataBinder.Eval(e.DataItem, "title"),
DataBinder.Eval (e.DataItem, "price")));
}
さらに、各項目がリスト ビューでレンダリングされる方法を制御することもできます。既定では、リスト ビューは 1 番目のフィールドを使用して各項目を表します。ただし、詳細ビューに表示されていないフィールドを含め、定義済みのフィールドまたは自動的に生成されたフィールドに LabelField プロパティを設定できます。前のサンプルを使用すると、Summary フィールドを項目のラベルとして使用し、詳細ビューでそのフィールドを非表示にできます。
ObjectList 内でデータ連結を実行する
ObjectList コントロールの内容が表示されるのは、コントロールがデータ ソースにバインドされている場合だけです。データ ソースには、IEnumerable インターフェイスまたは IListSource インターフェイスを実装している任意のオブジェクトを指定できます。ただし、データ ソースに含まれる各オブジェクトは、同じクラスのオブジェクトであるか、または同じ共通クラスを継承するオブジェクトであることが必要です。AutoGenerateFields が true に設定する場合、データ ソース内のオブジェクトを同じクラスのオブジェクトにする必要があります。
ObjectList コントロールは、データ ソース内のオブジェクトごとに ObjectListItem インスタンスを構築し、Items コレクションに格納します。このコレクションは、コードから検査できますが、変更はできません。
オブジェクト リストから参照するすべてのプロパティは、データ ソース内のすべてのオブジェクトに共通するクラスのパブリック プロパティであることが必要です。また、フィールドから参照するすべてのプロパティのデータ型は、連結可能型でなければなりません。有効な連結可能型には、String、DateTime、Decimal、およびプリミティブ型のセットがあります。
このコントロールは、データ ソース内のオブジェクトごとに、次のデータ連結処理を実行します。
フィールドごとに、ObjectList コントロールがフィールドの DataField プロパティを使用して、データ オブジェクトのどのプロパティを検索するかを判別します。それぞれの値は、インデックス フィールド値として ObjectListItem インスタンスに格納されます。
このようにしてすべてのフィールドをバインドした後、ObjectList コントロールに対して定義された ItemDataBind イベント ハンドラを呼び出します。このハンドラは、より複雑なデータ バインディングを実行したり、ObjectListItem インスタンス内の値を設定したりする目的で使用できます。
メモ :
ObjectList コントロールに加えた変更によっては、そのコントロール上のデータの再バインドが必要になることがあります。再バインドが必要になるのは、フィールドを追加または削除した場合、フィールドの DataField プロパティを変更した場合、およびフィールドの DataFormatString プロパティを変更した場合です。
データ連結中にフィールドの自動生成を開始する
データ バインディング時に、AutoGenerateFields プロパティが true に設定されていると、ObjectList コントロールがデータ ソースを検査し、フィールドを自動的に生成します。データ ソースが ITypedList 型のリストである場合、ObjectList コントロールはその型に関する情報を検査します。それ以外の場合、ObjectList コントロールは、リスト内の最初のオブジェクトの型情報を検査します。
検索した型の連結可能パブリック プロパティのそれぞれについて、ObjectList コントロールはプロパティに連結されたフィールドを生成します。これは、データ バインディング時に実行されます。フィールドに変更を加えた場合やフィールドを追加または削除した場合は、プロパティをもう一度バインドする必要があります。
自動生成されたフィールドは、既定で表示されます。その表示には、既定の書式が適用され、プロパティ名と同じタイトルが付与されます。これらの値はすべてプログラムから変更できます。また、プロパティに ObjectListTitleAttribute 属性を追加するとフィールドのタイトルも指定できます。たとえば、[ObjectListTitle("Address")]myAddress として宣言されたプロパティがある場合なら、生成されたフィールドのタイトルは "Address" となります。
ObjectList コントロールに明示的に定義されたフィールドがあれば、それらのフィールドの後で自動生成フィールドが追加されます。
次の例は、ObjectList コントロールのカスタム オブジェクトのリストを表示する方法を示します。
<%@ Page Language="VB"
Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<script runat="server">
Private customers(3) As Person
Private Class Person
Private _Name, _Nickname, _Initials As String
Public Sub New(ByVal name As String, _
ByVal nickname As String, _
ByVal initials As String)
Me._Name = name
Me._Nickname = nickname
Me._Initials = initials
End Sub
Public ReadOnly Property Name() As String
Get
Return _Name
End Get
End Property
Public ReadOnly Property Nickname() As String
Get
Return _Nickname
End Get
End Property
Public ReadOnly Property Initials() As String
Get
Return _Initials
End Get
End Property
End Class
Private Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs)
ReDim customers(2)
customers(0) = _
New Person("George Washington", "George", "GW")
customers(1) = _
New Person("Abraham Lincoln", "Abe", "AL")
customers(2) = _
New Person("Theodore Roosevelt", "Teddy", "TR")
If (Not IsPostBack) Then
' Bind the array to the list.
List1.DataSource = customers
List1.DataTextField = "Name"
List1.DataBind()
End If
End Sub
Protected Sub List1_ItemCommand( _
ByVal sender As Object, _
ByVal e As ListCommandEventArgs)
' Show the Summary text
Dim selectedPerson As Person = _
customers(e.ListItem.Index)
Label1.Text = _
String.Format("{0} (AKA {1}), initials {2}", _
selectedPerson.Name, _
selectedPerson.Nickname, _
selectedPerson.Initials)
ActiveForm = Form2
End Sub
Protected Sub Command1_Click(ByVal sender As Object, _
ByVal e As EventArgs)
Me.ActiveForm = Me.Form1
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<mobile:form id="Form1" runat="server">
<mobile:List ID="List1" Runat="server"
OnItemCommand="List1_ItemCommand" />
</mobile:form>
<mobile:Form ID="Form2" Runat="server">
<mobile:Label ID="Label1" runat="server" />
<mobile:Command ID="Command1" Runat="server"
StyleReference="subcommand"
OnClick="Command1_Click">
Return</mobile:Command>
</mobile:Form>
</body>
</html>
<%@ Page Language="C#"
Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<%@ Import Namespace="System.Collections" %>
<script runat="server">
private ArrayList customers = new ArrayList();
private class Person
{
private String _Name, _Nickname, _Initials;
public Person(String name, String nickname, String initials)
{
this._Name = name;
this._Nickname = nickname;
this._Initials = initials;
}
public String Name { get { return _Name; } }
public String Nickname { get { return _Nickname; } }
public String Initials { get { return _Initials; } }
}
private void Page_Load(object sender, System.EventArgs e)
{
customers.Add(
new Person("George Washington", "George", "GW"));
customers.Add(
new Person("Abraham Lincoln", "Abe", "AL"));
customers.Add(
new Person("Theodore Roosevelt", "Teddy", "TR"));
if(!IsPostBack)
{
// Bind the array to the list.
List1.DataSource = customers;
List1.DataTextField = "Name";
List1.DataBind();
}
}
private void List1_ItemCommand(object sender,
ListCommandEventArgs e)
{
Person selectedPerson = (Person)customers[e.ListItem.Index];
Label1.Text = String.Format("{0} (AKA {1}), initials {2}",
selectedPerson.Name, selectedPerson.Nickname,
selectedPerson.Initials);
ActiveForm = Form2;
}
protected void Command1_Click(object sender, EventArgs e)
{
this.ActiveForm = this.Form1;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<mobile:form id="Form1" runat="server">
<mobile:List ID="List1" Runat="server"
OnItemCommand="List1_ItemCommand">
</mobile:List>
</mobile:form>
<mobile:Form ID="Form2" Runat="server">
<mobile:Label ID="Label1" runat="server" />
<mobile:Command ID="Command1" Runat="server"
OnClick="Command1_Click">Return</mobile:Command>
</mobile:Form>
</body>
</html>
オブジェクト リスト内の項目にコマンドを関連付ける
ObjectList コントロールでは、1 つの項目にコマンドのセットを関連付けることができます。各コマンドには、そのコマンドを一意に識別する Name プロパティと、そのコマンドをレンダリングするための Text プロパティがあります。
このコントロールでコマンドを定義するには、次の 2 通りの方法があります。
宣言による定義。ObjectList コントロール内で <Command> 子要素を使用します。
プログラムによる定義。ObjectListCommand オブジェクトを作成し、コントロールの Commands コレクションに追加します。
既定では、リスト内のすべての項目が同じコマンド セットを共有します。しかし、コントロールが特定の項目のコマンド セットをレンダリングする前に ShowItemCommands イベントが発生するので、このイベントを処理するイベント ハンドラを用意すると、項目ごとにレンダリングするコマンドのセットを変更できます。
ユーザーがコマンドを選択すると、ItemCommand イベントが発生します。このイベントでは、選択された項目に関する情報と選択されたコマンドの名前が示されます。
ある項目に既定コマンドを定義した場合でも、Commands コレクションにコマンドを同じ名前で含める必要があります。これは、既定コマンドのショートカットを含む UI をレンダリングできない場合に、既定コマンドをコマンド セットの一部としてコントロールに表示させなければならないからです。
リスト項目のフィールド値にアクセスする
ObjectList コントロールにイベント ハンドラを関連付けると、リスト項目が対話型要素としてレンダリングされるようになります。リスト内の項目をクリックすると、その項目に対応する操作を取得するイベントが生成されます。データ連結中、各フィールドは対応するプロパティに連結されます。
ObjectListItem オブジェクトからフィールド値を取得するには、次の構文を使います。ここで、lstItem は ObjectListItem インスタンスを指します。
lstItem[fieldName]
次の例は前の例と似ていますが、各レコードに対して 2 つの Command コントロールを使用し、フィールド構文を使用してフィールド値を取得します。
<%@ Page Language="VB"
Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<%@ Import Namespace="System.Collections" %>
<script runat="server">
Public Class Person
' Private Fields
Private _Name, _Nickname, _Initials, _Wife As String
' Constructor
Public Sub New(ByVal name As String, _
ByVal nickname As String, ByVal initials As String, _
ByVal wife As String)
Me._Name = name
Me._Nickname = nickname
Me._Initials = initials
Me._Wife = wife
End Sub
' Public Properties
Public ReadOnly Property Name()
Get
Return _Name
End Get
End Property
Public ReadOnly Property Nickname()
Get
Return _Nickname
End Get
End Property
Public ReadOnly Property Initials()
Get
Return _Initials
End Get
End Property
Public ReadOnly Property Wife()
Get
Return _Wife
End Get
End Property
End Class
Private Sub Page_Load(ByVal sender As Object, _
ByVal e As EventArgs)
If Not IsPostBack Then
' An ArrayList for the Person objects
Dim customers As New ArrayList()
customers.Add( _
New Person("George Washington", "George", _
"GW", "Martha"))
customers.Add( _
New Person("Abraham Lincoln", "Abe", _
"AL", "Mary"))
customers.Add( _
New Person("Theodore Roosevelt", "Teddy", _
"TR", "Alice Lee"))
' Bind the array to the list.
ObjectList1.DataSource = customers
ObjectList1.LabelField = "Name"
ObjectList1.DataBind()
End If
End Sub
Protected Sub ObjectList1_ItemCommand( _
ByVal sender As Object, _
ByVal e As ObjectListCommandEventArgs)
If e.CommandName = "ShowSummary" Then
' Show the Summary text
Label1.Text = _
String.Format("{0}, AKA: '{1}', initials: '{2}'", _
e.ListItem("Name"), e.ListItem("Nickname"), _
e.ListItem("Initials"))
ElseIf e.CommandName = "MoreInfo" Then
' Show the More Info text
Label1.Text = String.Format("{0}'s wife was {1}", _
e.ListItem("Nickname"), e.ListItem("Wife"))
End If
Me.ActiveForm = Form2
End Sub
Protected Sub Command1_Click(ByVal sender As Object, _
ByVal e As EventArgs)
' Show the first form
Me.ActiveForm = Form1
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<mobile:form id="Form1" runat="server">
<mobile:ObjectList ID="ObjectList1" Runat="server"
CommandStyle-StyleReference="subcommand"
LabelStyle-StyleReference="title"
OnItemCommand="ObjectList1_ItemCommand">
<Command Name="ShowSummary" Text="Summary" />
<Command Name="MoreInfo" Text="More Info" />
</mobile:ObjectList>
</mobile:form>
<mobile:Form ID="Form2" Runat="server">
<mobile:Label ID="Label1" runat="server" />
<mobile:Command ID="Command1" Runat="server"
OnClick="Command1_Click">Return
</mobile:Command>
</mobile:Form>
</body>
</html>
<%@ Page Language="C#"
Inherits="System.Web.UI.MobileControls.MobilePage" %>
<%@ Register TagPrefix="mobile"
Namespace="System.Web.UI.MobileControls"
Assembly="System.Web.Mobile" %>
<%@ Import Namespace="System.Collections" %>
<script runat="server">
private class Person
{
// Private Fields
private String _Name, _Nickname, _Initials, _Wife;
// Constructor
public Person(string name, string nickname,
string initials, string wife)
{
this._Name = name;
this._Nickname = nickname;
this._Initials = initials;
this._Wife = wife;
}
// Public Properties
public String Name { get { return _Name; } }
public String Nickname { get { return _Nickname; } }
public String Initials { get { return _Initials; } }
public String Wife { get { return _Wife; } }
}
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
// An ArrayList for the Person objects
ArrayList customers = new ArrayList();
// Fill the Person object
customers.Add(
new Person("George Washington", "George",
"GW", "Martha"));
customers.Add(
new Person("Abraham Lincoln", "Abe",
"AL", "Mary"));
customers.Add(
new Person("Theodore Roosevelt", "Teddy",
"TR", "Alice Lee"));
// Bind the array to the list.
ObjectList1.DataSource = customers;
ObjectList1.LabelField = "Name";
ObjectList1.DataBind();
}
}
protected void ObjectList1_ItemCommand
(object sender, ObjectListCommandEventArgs e)
{
if (e.CommandName == "ShowSummary")
{
// Show the Summary text
Label1.Text =
String.Format("{0}, AKA: '{1}', initials: '{2}'",
e.ListItem["Name"], e.ListItem["Nickname"],
e.ListItem["Initials"]);
}
else if (e.CommandName == "MoreInfo")
{
// Show the More Info text
Label1.Text = String.Format("{0}'s wife was {1}",
e.ListItem["Nickname"], e.ListItem["Wife"]);
}
this.ActiveForm = Form2;
}
protected void Command1_Click(object sender, EventArgs e)
{
// Show the first form
this.ActiveForm = Form1;
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<body>
<mobile:form id="Form1" runat="server">
<mobile:ObjectList ID="ObjectList1" Runat="server"
CommandStyle-StyleReference="subcommand"
LabelStyle-StyleReference="title"
OnItemCommand="ObjectList1_ItemCommand">
<Command Name="ShowSummary" Text="Summary" />
<Command Name="MoreInfo" Text="More Info" />
</mobile:ObjectList>
</mobile:form>
<mobile:Form ID="Form2" Runat="server">
<mobile:Label ID="Label1" runat="server" />
<mobile:Command ID="Command1" Runat="server"
OnClick="Command1_Click">Return
</mobile:Command>
</mobile:Form>
</body>
</html>
ObjectList テンプレートでのデータ連結
ObjectList コントロールでは、テンプレートを定義してユーザー操作をカスタマイズできます。テンプレートでインラインのデータ バインディングを行う場合は、次のような構文を使用します。
<%#((ObjectListItem)Container)["BookName"]%>
また、次の例に示すように、DataBinder.Eval メソッドを使用すると、すべてのテンプレートでデータをバインドできます。
<%#DataBinder.Eval(((ObjectListItem)Container).DataItem,"fieldname")%>