WPFtoolkit and its DatagridColumnHeader - datagrid

I need to have different context menus in my datagrid - one for its header and one for rows of a grid. So I'm handling MouseClick event and than I need to evaluate if the underlying object for mouse cursor is Datagrid's header. Can you explain me how can I make this?
The thing that I can't understand is that neither of DataGrid's and DataGridColumn's hierarchy of objects contain DataGridColumnHeader object or any reference to it. But in virtual tree if I get textblock that is located in header and contains column header's text and then get it parent container, I'll get DatagridColumnHeader object.
Any help is appreciated. Thanks in advance!

Private Sub DGrid_MouseLeftButtonDown(ByVal sender As System.Object, ByVal e As System.Windows.Input.MouseButtonEventArgs)
Dim dep As DependencyObject = DirectCast(e.OriginalSource, DependencyObject)
' iteratively traverse the visual tree
While (dep IsNot Nothing) AndAlso Not (TypeOf dep Is DataGridRow OrElse TypeOf dep Is Primitives.DataGridColumnHeader OrElse TypeOf dep Is DataGrid)
dep = VisualTreeHelper.GetParent(dep)
End While
If dep Is Nothing Then
Exit Sub
End If
If TypeOf dep Is Primitives.DataGridColumnHeader Then
Dim CurrentHeader As Primitives.DataGridColumnHeader = TryCast(dep, Primitives.DataGridColumnHeader)
If Not CurrentHeader Is Nothing Then
CurrentHeader.ContextMenu.Items.Add("Option")
End If
ElseIf TypeOf dep Is DataGridRow Then
'Something else
End If
End Sub

Related

Maintain Tab index after post back with textchanged

I have 3 textboxes that have AutoPostBack = true. On postback it's losing it's focus. I've been searching and tried many things but nothing is working.
The code below is a snippet of what i'm trying to do.
basically this first snippet isn't grabbing anything. Does anyone know what i'm doing wrong here
**Side note I'm not using Update Panel i'm using LayoutItemNestedControlContainer
Dim ctrl = From control In wcICausedPostBack.Parent.Controls.OfType(Of WebControl)()
Where control.TabIndex > indx
Select control
Protected Sub txtDEPTH_TextChanged(sender As Object, e As EventArgs) Handles txtDEPTH.TextChanged
UpdateProductTemp()
txtDEPTH.Focus()
End Sub
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Page.IsPostBack Then
Dim wcICausedPostBack As WebControl = CType(GetControlThatCausedPostBack(TryCast(sender, Page)), WebControl)
Dim indx As Integer = wcICausedPostBack.TabIndex
Dim ctrl = From control In wcICausedPostBack.Parent.Controls.OfType(Of WebControl)()
Where control.TabIndex > indx
Select control
ctrl.DefaultIfEmpty(wcICausedPostBack).First().Focus()
End If
End Sub
Protected Function GetControlThatCausedPostBack(ByVal page As Page) As Control
Dim control As WebControl = Nothing
Dim ctrlname As String = page.Request.Params.[Get]("__EVENTTARGET")
If ctrlname IsNot Nothing AndAlso ctrlname <> String.Empty Then
control = page.FindControl(ctrlname)
Else
For Each ctl As String In page.Request.Form
Dim c As Control = page.FindControl(ctl)
If TypeOf c Is TextBox OrElse TypeOf c Is DropDownList Then
control = c
Exit For
End If
Next
End If
Return control
End Function
Which version are you using? Because, when I try to set focus() of a Textbox, the compiler gives me an error, because there is no such method. However, HTML provides an attribute, which auto focuses an focusable element.
Solution:
TextBoxToSetFocus.Attributes.Add("autofocus", "")
Regards,
Maheshvara

Telerik radgrid row color issue

In my code I have this sub to handle changing row colors depending on the contents of a column called "backorder" which is bit in sqlserver.
When I test if it is True or 1 it executes the main "IF" code twice which is correct for my datatable. 2 rows display as backorder = True. However the grid remains the normal color. If I uncomment the else code block, ALL cells in that column are orange regardless of content and the execution still passed thru the main "IF" twice. I am quite confused by this behavior. If it was CSS interfering, why would it let the orange color work? I have tried a dozen variations of code which all posters say should work...
Please help! I have spent most of the day trying to unravel this!
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = DirectCast(e.Item, GridDataItem)
If item("backorder").Text = "True" Or item("backorder").Text = "1" Then
item("backorder").BackColor = System.Drawing.Color.Red
Else
'item("backorder").BackColor = System.Drawing.Color.Orange
End If
End If
End Sub
Your problem is that item("backorder") returns an object of type TableCell, not a row. Therefore, when setting item("backorder").BackColor = System.Drawing.Color.Red you are setting the cell in the column backorder's BackColor, not the entire rows backcolor. If the Column backorder is not visible, you wont see any change.
Try the following code:
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = DirectCast(e.Item, GridDataItem)
If item("backorder").Text = "True" Or item("backorder").Text = "1" Then
item.BackColor = Drawing.Color.Red
Else
item.BackColor = System.Drawing.Color.Orange
End If
End If
End Sub
What this does is check the column 'backorder', and then sets the entire rows BackColor by setting the BackColor for the GridDataItem.
Check out Shinu's answer in the following post. Telerik Forum Post
It may be related to the Boolean evaluation you're doing. You've accounted for "True" and 1, but there are others: "true", and -1 come immediately to mind. You might try this instead:
Protected Sub RadGrid1_ItemDataBound(sender As Object, e As Telerik.Web.UI.GridItemEventArgs) Handles RadGrid1.ItemDataBound
If TypeOf e.Item Is GridDataItem Then
Dim item As GridDataItem = DirectCast(e.Item, GridDataItem)
If Convert.ToBoolean(item("backorder").Text) = True Then
item("backorder").BackColor = System.Drawing.Color.Red
Else
item("backorder").BackColor = System.Drawing.Color.Orange
End If
End If
End Sub
That way, you're letting the built-in Convert object handle the heavy-lifting on the "truthiness" of the statement contained in the string.

Unable to cast object of type 'System.Web.UI.WebControls.RadioButtonList' to type 'System.Web.UI.WebControls.TableRow'

I have a 4 tier architecture using asp.net 4.0
1- Web application
2- Business object
3- Business Logic
4- Data Logic
i have used factory method to create dynamic forms. on a radio button list selected index changed event , i want to hide/show a table row which is also created dynamically. table row is available in session. i am using the following code
Private Sub parameter_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Try
Dim rdbtn As RadioButtonList = DirectCast(sender, RadioButtonList)
Dim selectedText As String = rdbtn.SelectedItem.Text
Dim worksRequiredRowId = SessionManager.getWorksRequiredRowId()
Dim worksRequiredRow As TableRow = CType(sender.FindControl(worksRequiredRowId), TableRow)
If selectedText.ToUpper <> ApplicationConstants.conditionSatisfactory.ToUpper Then
worksRequiredRow.Style.Add("display", "table-row")
Else
worksRequiredRow.Style.Add("display", "none")
End If
Catch ex As Exception
End Try
End Sub
And i get the following error.
Unable to cast object of type
'System.Web.UI.WebControls.RadioButtonList' to type
'System.Web.UI.WebControls.TableRow'.
Please help me to find out the solution.
Best ragards.
You can actually hide that particular item from radio button list instead of converting it into table row. Something like this.
If rdbtn.SelectedItem.Text <> selectedText.ToUpper <> ApplicationConstants.conditionSatisfactory.ToUpper Then
rdbtn.Items(itemIndex).Attributes.CssStyle.Add("display", "none")
End If
I hope this helps.
I think your mistake is confusing the generated HTML markup with the raw ASP.NET markup. RadioButtonList does create an HTML for each item, but you can't access that rows at the server-side (to make them visible or hidden).
You should either use the server-side method mentioned in Bridewin D.P.'s answer or transfer the code to client-side and use Javascript to manipulate the rows.
Server-side would look something like this:
Private Sub parameter_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
Try
Dim rdbtn As RadioButtonList = DirectCast(sender, RadioButtonList)
Dim selectedText As String = rdbtn.SelectedItem.Text
Dim worksRequiredRowId = SessionManager.getWorksRequiredRowId()
Dim style as String
If selectedText.ToUpper <> ApplicationConstants.conditionSatisfactory.ToUpper Then
style= "table-row"
Else
style= "none"
End If
rdbtn.Items(worksRequiredRowId).Attributes.CssStyle.Add("display", style)
Catch ex As Exception
End Try
End Sub

Modifying a copy of a Collection from with a For Each still gives error

I am trying to scan through some True/False RadioButtonLists that I have. They're within an QuestionsList. I am trying to add a message to each item saying "Correct" or "Incorrect", but when I do so I get "Collection was modified; enumeration operation may not execute."
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
If (IsPostBack) Then
Dim SubmittedQuestionsList As New HtmlGenericControl("ol")
SubmittedQuestionsList = QuestionsList
For Each QuestionItem In SubmittedQuestionsList.Controls
If TypeOf QuestionItem Is HtmlGenericControl Then
For Each question In QuestionItem.Controls
If TypeOf question Is RadioButtonList Then
Dim QuestionExplanation As New Panel
If (question.SelectedValue = "true") Then
QuestionExplanation.CssClass = "succcess-response"
QuestionExplanation.Controls.Add(New LiteralControl("Correct!"))
Else
QuestionExplanation.CssClass = "error-response"
QuestionExplanation.Controls.Add(New LiteralControl("Incorrect:"))
End If
'If I uncomment the line below, error goes away
QuestionsList.Controls.Add(QuestionExplanation)
Debug.WriteLine(question.SelectedValue)
End If
Next
End If
Next
End If
End Sub
What is the best way to loop through it (or a copy of it), and add a message as I go?
Per Dave's comment, noting that SubmittedQuestionsList was simply a reference to QuestionsList, I found I could simply use an Array.
Replace:
Dim SubmittedQuestionsList As New HtmlGenericControl("ol")
SubmittedQuestionsList = QuestionsList
with:
Dim SubmittedQuestionsList(QuestionsList.Controls.Count) As HtmlGenericControl
QuestionsList.Controls.CopyTo(SubmittedQuestionsList, 0)

FinByValue not working within context of a UserControl DropDownList

I am pulling my hair out with this one.
I have an Employee dropdownlist usercontrol (uxEmployee) and I have exposed the SelectedValue method as a property(SelectedValue).
Within my page I am trying to either set the value based on my data or add the value to the list if it is not currently on there.
No matter what I do it is adding the Set value to the list. Even when the value is already on the list; it is still adding the value. Basically FindByValue is always returning "Nothing" no matter what I do. Any help would be appreciated.
Public Property SelectedValue() As String
Get
Return uxEmployee.SelectedValue
End Get
Set(ByVal value As String)
If Not uxEmployee.Items.FindByValue(value) Is Nothing Then
uxEmployee.SelectedValue = value
Else
uxEmployee.Items.Insert(0, New ListItem(value, value))
uxEmployee.AppendDataBoundItems = True
uxEmployee.DataBind()
End If
End Set
End Property
Public WriteOnly Property Department() As String
Set(ByVal value As String)
_department = value
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not (IsPostBack) Then
Dim emp As New Employee()
With uxEmployee
If _department <> String.Empty Then
.DataSource = emp.GetByDept(_department)
Else
.DataSource = emp.GetList()
End If
.DataTextField = "FullName"
.DataValueField = "UserName"
.DataBind()
End With
End If
End Sub
my calling page uses the following in page load.. uxSalesleadv is an instance of uxemployee
Dim objPrj As ServiceProject = New ServiceProject()
objPrj = objPrj.GetItem(prjID)
With objPrj
uxSalesLead.SelectedValue = .SalesLead
End With
The method performs an exact match and is case-sensitive and culture-insensitive. Have you checked that the values are identical in the debugger?
Try using FindByName(). If it works, then the values are not being set properly when you initially set the data source.
After much trial and error and debugging I have figured out the problem.
I was able to get the control to work correctly when i moved my data assignment from the page_load to the pre_render event. This was not ideal though.. I eventually found that the usercontrol was setting the value before the actual databinding was taking place.
I have now moved the logic out of my Set property and now added logic to my controls page_load databinding to check if the previous SET value is in the databind list. If it isnt then it adds the item. This will allow me to use the usercontrol throughout my apps without any additional page code and worrying about item not in list errors.

Resources