Mr.Tです、こんにちは。
http://blogs.wankuma.com/mrt/archive/2007/09/13/96121.aspx#FeedBackの続きになりますかね。
そもそも、Evalを使わないとなると明示的にCastすることになります。Castはいいんですが、
<ItemTemplate>
<tr>
<td><%# ((DbDataRecord)Container.DataItem).GetString(0) %></td>
<td><%# ((DbDataRecord)Container.DataItem).GetInt(1) %></td>
</tr>
</ItemTemplate>
こんな使い方になりますね。(C#ですけど)えらく面倒というか、やはりもっと明示的に、直感的に指定したいです。
たとえば、表示したいViewは、こんなのとします。
| 工場コード | 工場名 |
| 10 | 工場A |
| 20 | 工場B |
| 30 | 工場C |
単なるマスタですが、そもそもこんな感じで表示するケースが基本じゃないかと思います。
で、これを表示するためのソースです。
(データソースコントロール)
Namespace MRT.OriginalControls
'製造原価関連データベースへのアクセス用 データソース基底クラス
' データソースクラス
<AspNetHostingPermission(SecurityAction.LinkDemand, _
level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(SecurityAction.InheritanceDemand, _
level:=AspNetHostingPermissionLevel.Minimal), _
ToolboxData("<{0}:OriginalDataSource runat=""Server""/>"), _
Description("カスタムデータソース")> _
Public Class OriginalSource
Inherits DataSourceControl
' Implements IDataSourceOtherControlParameter
Private Const DefaultViewName As String = "defaultview"
'唯一のView名を返す
Protected Overrides Function GetViewNames() As System.Collections.ICollection
Dim viewNames() As String = New String() {DefaultViewName}
Return CType(viewNames, ICollection)
End Function
'既定のViewを返す
Private _defaultView As OriginalDataSorceView
Private ReadOnly Property DefaultView() As OriginalDataSorceView
Get
If (_defaultView Is Nothing) Then
_defaultView = New OriginalDataSorceView(Me, DefaultViewName)
End If
Return _defaultView
End Get
End Property
Protected Overrides Function GetView(ByVal viewName As String) As System.Web.UI.DataSourceView
If (viewName = String.Empty) Or _
(viewName.ToLower = DefaultViewName.ToLower) Then
Return DefaultView
End If
Throw New ArgumentOutOfRangeException(viewName)
End Function
End Class
'規定のDataSourceView
Public Class OriginalDataSorceView
Inherits DataSourceView
' Implements IDataSourceOtherControlParameter
Private _owner As OriginalSource
Public Sub New(ByVal owner As OriginalSource, ByVal name As String)
MyBase.New(owner, name)
_owner = owner
End Sub 'New
'ここでSelectしまっせ。
Protected Overrides Function ExecuteSelect(ByVal arguments As System.Web.UI.DataSourceSelectArguments) As System.Collections.IEnumerable
Dim connectionString As String = "Data Source=****"
Dim targetStoredProcedure As String = "dbo.GetFactoryTable"
Dim targetDataReader As SqlDataReader
Dim targetView As Queue(Of FactoryView) = New Queue(Of FactoryView)
Using targetSQLConnection As SqlConnection = New SqlConnection(connectionString)
Using targetSQLCommand As SqlCommand = New SqlCommand(targetStoredProcedure, targetSQLConnection)
'処理はパラメータ追加してのち、ストアドで実行
targetSQLCommand.Connection.Open()
targetSQLCommand.CommandType = CommandType.StoredProcedure
targetDataReader = targetSQLCommand.ExecuteReader(CommandBehavior.CloseConnection)
Dim fieldsCount As Integer = targetDataReader.FieldCount
While targetDataReader.Read()
Dim newView As FactoryView = New FactoryView
newView.FactoryCD = targetDataReader.GetValue(0).ToString
newView.FactoryName = targetDataReader.GetValue(1).ToString
targetView.Enqueue(newView)
End While
Return targetView
End Using
End Using
End Function
End Class
'アクセスされるView
Public Class FactoryView
Private _factoryCD As String
Public Property FactoryCD() As String
Get
Return _factoryCD
End Get
Set(ByVal value As String)
_factoryCD = value
End Set
End Property
Private _factoryName As String
Public Property FactoryName() As String
Get
Return _factoryName
End Get
Set(ByVal value As String)
_factoryName = value
End Set
End Property
End Class
End Namespace
(表示コントロール)
Namespace MRT.OriginalControls
'リスト表示するためのカスタムコントロール
<AspNetHostingPermission(System.Security.Permissions.SecurityAction.Demand, _
level:=AspNetHostingPermissionLevel.Minimal), _
AspNetHostingPermission(System.Security.Permissions.SecurityAction.InheritanceDemand, _
level:=AspNetHostingPermissionLevel.Minimal), _
ToolboxData("<{0}:OriginalList runat=""Server""></{0}:OriginalList>"), _
Description("リスト表示用カスタム"), _
ParseChildren(True)> _
Public Class OriginalList
Inherits CompositeDataBoundControl
Private targetItemTemplate As ITemplate
'コンテナ設定箇所
<PersistenceMode(PersistenceMode.InnerProperty), _
TemplateContainer(GetType(MasterContainer))> _
Public Overridable Property ItemTemplate() As ITemplate
Get
Return targetItemTemplate
End Get
Set(ByVal value As ITemplate)
targetItemTemplate = value
End Set
End Property
'コントロール作成部分
Protected Overrides Function CreateChildControls(ByVal dataSource As IEnumerable, _
ByVal dataBinding As Boolean) As Integer
Dim loopCount As Integer = 0
Dim targetEnumerator As IEnumerator = dataSource.GetEnumerator
Dim listItemView As MasterContainer
Controls.Clear()
While targetEnumerator.MoveNext()
listItemView = New MasterContainer(CType(targetEnumerator.Current, FactoryView))
'テンプレートへの格納
'上記のITemplateは、テンプレート適用のためのプロパティ
targetItemTemplate.InstantiateIn(listItemView)
If (dataBinding = True) Then
'バインドしないものはデータバインド処理にならない
listItemView.DataBind()
End If
Controls.Add(listItemView)
loopCount += 1
End While
Return loopCount
End Function
End Class
'コンテナ
Public Class MasterContainer
Inherits Control
Implements INamingContainer '一意の名前をつけるために必要
Public Sub New(ByVal targetView As FactoryView)
FactoryItem = targetView
End Sub
Private _factoryItem As FactoryView
Public Property FactoryItem() As FactoryView
Get
Return _factoryItem
End Get
Set(ByVal value As FactoryView)
_factoryItem = value
End Set
End Property
End Class
End Namespace
(ASPXファイル)
<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="_Default" %>
<%@ Register TagPrefix="MyControl" Namespace="MRT.OriginalControls"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>無題のページ</title>
</head>
<body>
<form id="form1" runat="server">
<MyControl:OriginalSource runat="server" ID="OriginalDataSource1" />
<table border ="1">
<MyControl:OriginalList runat="server" ID="list1" DataSourceID="OriginalDataSource1">
<ItemTemplate>
<tr><td><%# container.FactoryItem.FactoryCD%></td><td><%# container.FactoryItem.FactoryName%></td></tr>
</ItemTemplate>
</MyControl:OriginalList>
</table>
</form>
</body>
</html>
とりあえず、ひとつのViewだけが対象になってるので、ソレ(ここではFactoryView)しか出てきません。
それに、取得条件も変更できるようにはなっていませんが...
container.FactoryItem.FactoryCD
こうやって、かけるようになりました。ありがとう>菊池さん
さて、菊池さんのBlogではExecuteSelectの部分がのってません。当たり前ですが、ここは何を扱うかで中身が
違うからなんですね。
キモは、IEnumerable で返さないといけないってことです。
今回はQueueを使いましたが、順序とか特にきにしないなら、Listでも返せます。