How to improve the design of a page with multiple case statements
My page contains: GridView1, GridView2, Button1, Button2, DropDownList1 I bind Gridviews to the table selected in dropdown like this:
Dim results as DataTable
Select Case ddl1.SelectedValue
Case 0
results = dtZero
Case 1
results = dtOne
Case 2
results = dtTwo
Case 3
results = dtThree
End Select
GridView1.DataSource = results
GridView1.DataBind()
Then I have two buttons with the following code:
Protected Sub btn1_Click(sender As Object, e As EventArgs) Handles btn2.Click
Select Case ddl1.SelectedValue
Case 0
RunZero()
Case 1
RunOne()
Case 2
RunTwo()
Case 3
RunThree()
End Select
End Sub
And
Protected Sub btn2_Click(sender As Object, e As EventArgs) Handles btn2.Click
Select Case ddl1.SelectedValue
Case 0
RemoveZero()
Case 1
RemoveOne()
Case 2
RemoveTwo()
Case 3
RemoveThree()
End Select
End Sub
For me it looks like a lot of overhead. How can I improve then design and only specify that I'm working on the following record in dropdown list without specifying the Case
condition every time? Should I change my design or leave it like it is?
Update:
RunZero
, RunOne
, RunTwo
, RemoveZero
, RemoveOne
, RemoveTwo
, RemoveThree
开发者_C百科- Execute six different stored procedures.
This was a fun one to solve. Thank you.
Sounds like you should be using actions.
First Create a class that will keep track of all your "operations" represented by your dropdownlist...
EDIT: Using Actions instead to show that you can use parameters for your functions if you want or not.
Class OpMode
Public DropDownKey As String
Public RunFunction As Action(Of Int32) 'This one will support a parameter'
Public RemoveFunction As Action
Public dt As Data.DataTable
Sub New(DropDownKey As String, RunFunction As Action(Of Int32), RemoveFunction As Action, dt As Data.DataTable)
Me.DropDownKey = DropDownKey
Me.RunFunction = RunFunction
Me.RemoveFunction = RemoveFunction
Me.dt = dt
End Sub
End Class
You should already have methods for running your procs.
EDIT: In this example I've allowed a parameter for the "Run" procs...
Private Sub RunOne(MyVariable As Int32)
Response.Write("RunOne")
End Sub
Private Sub RunTwo(MyVariable As Int32)
Response.Write("RunTwo")
End Sub
Private Sub RemoveOne()
Response.Write("RemoveOne")
End Sub
Private Sub RemoveTwo()
Response.Write("RemoveTwo")
End Sub
I assume you have those datatables somewhere...
Private dtOne As New Data.DataTable
Private dtTwo As New Data.DataTable
Create a readonly property to hold all your OpModes you want to use. It's light to recreate so no need to cache it.
Private ReadOnly Property OpModes As List(Of OpMode)
Get
Dim _OpModes As New List(Of OpMode)
_OpModes.Add(New OpMode("1", AddressOf RunOne, AddressOf RemoveOne, dtOne))
_OpModes.Add(New OpMode("2", AddressOf RunTwo, AddressOf RemoveTwo, dtTwo))
Return _OpModes
End Get
End Property
Make a function for searching through your list of opmodes for the one that matches your dropdownlist...
Private Function GetOpByDropDownKey(DropDownKey As String) As OpMode
Return (From x In OpModes Where x.DropDownKey = DropDownKey).First
End Function
Make a click event that works for both buttons and invokes the appropriate method...
EDIT: In this example, the RunFunction
has a parameter but the RemoveFunction
does not.
Private Sub btn_Click(sender As Object, e As System.EventArgs) Handles btn1.Click, btn2.Click
With GetOpByDropDownKey(dd1.SelectedValue)
If sender Is btn1 Then
.RunFunction(12345)
Else
.RemoveFunction()
End If
End With
End Sub
Now you can bind the correct datatable programmatically...
GridView1.DataSource = GetOpByDropDownKey(dd1.SelectedValue).dt
GridView1.DataBind()
This should be a lot easier to maintain once you get it working. You will have less places where you could have accidently forgotten to include an item in your case statement, since all that definition is defined once in your readonly property.
EDIT: (Removed note about delegates. Actions are all you need.)
I hope this helps you.
EDIT: This is suitable for VB.Net only, not ASP.Net.
A simpler way to acomplish this is to create a class with a ToString function and populate the list with that.
Class OpInfo
Public Sub New(ByVal Text As String, ByVal DataTable As DataTableSelect, ByVal RunMethod As Action, ByVal RemoveMethod As Action)
_Text = Text
_DataTable = DataTable
_RunMethod = RunMethod
_RemoveMethod = RemoveMethod
End Sub
Public ReadOnly Property DataTable As DataTableSelect
Get
Return _DataTable
End Get
End Property
Private _DataTable As DataTableSelect
Public Sub Run()
_RunMethod()
End Sub
Private _RunMethod As Action
Public Sub Remove()
_RemoveMethod()
End Sub
Private _RemoveMethod As Action
Public Function Overrides ToString() As String
Return _Text
End Function
Private _Text As String
End Class
You can populate the list with instances of this class. By type casting the selected item, you have access to all of its members.
Class Form1
Public Sub New()
InitializeComponents()
ddl1.Items.Add(New OpInfo("Zero", dtZero , AddressOf RunZero , AddressOf RemoveZero )
ddl1.Items.Add(New OpInfo("One", dtOne , AddressOf RunOne , AddressOf RemoveOne )
ddl1.Items.Add(New OpInfo("Two", dtTwo , AddressOf RunTwo , AddressOf RemoveTwo )
ddl1.Items.Add(New OpInfo("Three", dtThree, AddressOf RunThree, AddressOf RemoveThree)
End Sub
Protected Sub ddl1_SelectedIndexChanged(sender As Object, e As EventArgs)
If ddl1.SelectedIndex = -1 Then
' Code for when nothing is selected.
Else
GridView1.DataSource = CType(ddl1.SelectedItem, OpInfo).DataTable
GridView1.DataBind()
End If
End Sub
Protected Sub btn1_Click(sender As Object, e As EventArgs) Handles btn2.Click
If ddl1.SelectedIndex <> -1 Then CType(ddl1.SelectedItem, OpInfo).Run
End Sub
Protected Sub btn2_Click(sender As Object, e As EventArgs) Handles btn2.Click
If ddl1.SelectedIndex <> -1 Then CType(ddl1.SelectedItem, OpInfo).Remove
End Sub
End Class
精彩评论