I'm trying to accomplish inline editing with a DevExpress ASPxTreeList control on an ASP.NET 4.5 webforms application - something like this (taken from the DevExpress demo site):
What I'm trying to do are two things:
I'd like to be able to restrict my inline editing to just a few columns - e.g. only the Budget column should be editable. I'd like to have only the Budget cell turn into a textbox to allow data entry - while all other columns in the chosen row should remain as is - as labels basically (right now, when I enable inline editing, all cells turn into editable controls - they turn into a textbox that would suggest editing is possible)
I would love to be able to just click (or double-click) into that cell to enable inline editing - for now, I need to use a separate command button to "turn on" editing. How can I do this (if at all)?
If you want labels instead of editable controls, then you can simply use EditCellTemplate with label control inside.
Here is example:
<dx:TreeListDataColumn FieldName="ContactName">
<EditCellTemplate>
<dx:ASPxLabel ID="ASPxLabel1" runat="server" Value='<%# Eval("ContactName") %>' />
</EditCellTemplate>
</dx:TreeListDataColumn>
This functionality for ASPxTreeList does not implemented by DevExpress. They have suggestion in their Support Center to implement «ASPxTreeList - Implement BatchEdit mode (like in ASPxGridView)». Here you can take a look at how it works in ASPxGridView.
So, here is workaround, based on this example.
The main goal is to use DataCellTemplate for columns with ASPxTextBox control as value editor. The ASPxTextBox can be fully customized by applying a specific style to each composite editor element. This allows to simulate the desired behavior. You can hide the borders and background of ASPxTextBox and show the borders only when ASPxTextBox is focused.
Here is example:
<script>
function GotFocus(s, e) {
s.inputElement.style.cursor = "text";
}
function LostFocus(s, e) {
s.inputElement.style.cursor = "default";
}
</script>
<dx:ASPxTreeList ID="ASPxTreeList1" ClientInstanceName="tree" runat="server" Width="100%"
DataSourceID="AccessDataSource1" AutoGenerateColumns="False" KeyFieldName="CategoryID"
OnCustomCallback="ASPxTreeList1_CustomCallback">
<Columns>
<dx:TreeListTextColumn FieldName="CategoryID" ReadOnly="True" VisibleIndex="0">
</dx:TreeListTextColumn>
<dx:TreeListTextColumn FieldName="CategoryName" VisibleIndex="1">
<DataCellTemplate>
<dx:ASPxTextBox
ID="txtBox"
Width="100%"
runat="server"
Value='<%# Eval("CategoryName") %>'
Cursor="default"
BackColor="Transparent"
Border-BorderColor="Transparent"
FocusedStyle-Border-BorderColor="ActiveBorder"
ClientSideEvents-GotFocus="GotFocus"
ClientSideEvents-LostFocus="LostFocus" />
</DataCellTemplate>
</dx:TreeListTextColumn>
<dx:TreeListTextColumn FieldName="Description" VisibleIndex="2">
<DataCellTemplate>
<dx:ASPxTextBox
ID="txtBox"
Width="100%"
runat="server"
Value='<%# Eval("Description")%>'
Cursor="default"
BackColor="Transparent"
Border-BorderColor="Transparent"
FocusedStyle-Border-BorderColor="ActiveBorder"
ClientSideEvents-GotFocus="GotFocus"
ClientSideEvents-LostFocus="LostFocus"/>
</DataCellTemplate>
</dx:TreeListTextColumn>
</Columns>
<Border BorderWidth="0px" />
</dx:ASPxTreeList>
<dx:ASPxButton ID="ASPxButton1" runat="server" AutoPostBack="False" Text="Post Modifications"
Width="217px">
<ClientSideEvents Click="
function(s, e) {
tree.PerformCallback('post');
}" />
</dx:ASPxButton>
<asp:AccessDataSource ID="AccessDataSource1" runat="server" DataFile="~/App_Data/nwind.mdb"
SelectCommand="SELECT * FROM [Categories]"
UpdateCommand="UPDATE [Categories] SET [CategoryName] = ?, [Description] = ? WHERE [CategoryID] = ?">
<UpdateParameters>
<asp:Parameter Name="CategoryName" Type="String" />
<asp:Parameter Name="Description" Type="String" />
<asp:Parameter Name="CategoryID" Type="Int32" />
</UpdateParameters>
</asp:AccessDataSource>
private List<Record> list = new List<Record>();
protected void Page_Load(object sender, EventArgs e)
{
var column1 = ASPxTreeList1.DataColumns["CategoryName"];
var column2 = ASPxTreeList1.DataColumns["Description"];
var nodes = ASPxTreeList1.GetVisibleNodes();
foreach (var node in nodes)
{
var txtBox1 = (ASPxTextBox)ASPxTreeList1.FindDataCellTemplateControl(node.Key, column1, "txtBox");
var txtBox2 = (ASPxTextBox)ASPxTreeList1.FindDataCellTemplateControl(node.Key, column2, "txtBox");
if (txtBox1 == null || txtBox2 == null)
continue;
int id = Convert.ToInt32(node.Key);
list.Add(new Record(id, txtBox1.Text, txtBox2.Text));
}
}
protected void ASPxTreeList1_CustomCallback(object sender, TreeListCustomCallbackEventArgs e)
{
if (e.Argument == "post")
{
for (int i = 0; i < list.Count; i++)
{
AccessDataSource1.UpdateParameters["CategoryName"].DefaultValue = list[i].CategoryName;
AccessDataSource1.UpdateParameters["Description"].DefaultValue = list[i].Description;
AccessDataSource1.UpdateParameters["CategoryID"].DefaultValue = list[i].Id.ToString();
// AccessDataSource1.Update(); << Uncomment this line to update data!
}
ASPxTreeList1.DataBind();
}
}
Related
I want to save text box enter value in database and this text box is present inside Detailed GridView so i can not even access Directly neither child grid and nor TextBox.
Can any one help me on same
ASPX
<dx:ASPxGridView ID="dgDepots" runat="server" ClientInstanceName="gv"
KeyFieldName="LineItemID" Width="100%" OnInitNewRow="dgDepots_InitNewRow" OnDataBinding="dgDepots_DataBinding"
<column>
//master grid column//
<DetailRow>
<dx:ASPxGridView ID="dgProducts" ClientInstanceName="dgProducts" runat="server" AutoGenerateColumns="False" KeyFieldName="ProductLineItemID" OnCellEditorInitialize="dgProducts_CellEditorInitialize"
OnDataBinding="dgProducts_DataBinding" OnBeforePerformDataSelect="dgProducts_BeforePerformDataSelect"
OnRowUpdating="dgProducts_RowUpdating" CellStyle-HorizontalAlign="Center">
<Columns>
<dx:GridViewDataColumn FieldName="QuantityInPieces" VisibleIndex="4">
<EditItemTemplate>
<dx:ASPxTextBox ID="txt" OnInit="txt_Init" runat="server" Width="100%"></dx:ASPxTextBox>
</EditItemTemplate>
</dx:GridViewDataColumn>
.cs
protected void dgProducts_RowInserting(object sender, DevExpress.Web.Data.ASPxDataInsertingEventArgs e)
{
for (int i = 0; i < dgDepots.VisibleRowCount; i++)
{
ASPxTextBox tb = dgDepots.FindRowCellTemplateControl(i, dgDepots.Columns["QuantityInPieces"] as GridViewDataColumn, "QuantityInPieces") as ASPxTextBox;
string payment = tb.Text;
//ObjInvoices.SellerID = Convert.ToInt32(dgDepots.GetRowValues(i, "txt"));
}
I have a GridView which has two session vairables used to filter the select statement (TimeStart and TimeFinish). I have a default value for these, which displays the correct information in the GridView.
I have two ASP TextBoxes with TextMode set to Time which I need to update these values. These update the session variables (have set a label's value to check), but do not update the select statement of my GridView.
I've done something Identical for another GridView on the same page, the only difference being that the session variable in an Int32 and being set from a GridView's IndexChanged event, and am confused as to why it's not working for this one.
Source for GridView:
<asp:GridView ID="gvAvailableVets" runat="server" AutoGenerateColumns="False" DataKeyNames="VetID" DataSourceID="AvailableVetsDataSource">
<Columns>
<asp:BoundField DataField="VetID" HeaderText="VetID" ReadOnly="True" SortExpression="VetID" />
<asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
<asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="MobileNumber" HeaderText="MobileNumber" SortExpression="MobileNumber" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="AvailableVetsDataSource" runat="server" ConnectionString="<%$ ConnectionStrings:VetPracticeConnectionString %>" SelectCommand="SELECT DISTINCT Veternarians.VetID, FirstName, LastName, MobileNumber FROM dbo.Veternarians
INNER JOIN dbo.VetHours
ON Veternarians.VetID = VetHours.VetID
INNER JOIN dbo.Appointments
ON Veternarians.VetID = Appointments.VetID
WHERE #beginTime > VetHours.StartTime
AND #endTime < VetHours.EndTime
AND (#beginTime > Appointments.EndTime
OR #endTime < Appointments.BeginTime) ">
<SelectParameters>
<asp:SessionParameter DefaultValue="9:00" Name="beginTime" SessionField="TimeStart" Type="String" />
<asp:SessionParameter DefaultValue="10:00" Name="endTime" SessionField="TimeFinish" Type="String" />
</SelectParameters>
</asp:SqlDataSource>
C# code behind for the TextBoxes:
protected void txtTimeBegin_TextChanged(object sender, EventArgs e) {
Session["TimeStart"] = txtTimeBegin.Text;
// Used for debugging
lblDebug.Text = Session["TimeStart"].ToString();
}
protected void txtTimeEnd_TextChanged(object sender, EventArgs e) {
Session["TimeFinish"] = txtTimeEnd.Text;
}
Try to rebind your Gridview when any textbox value changed.
protected void txtTimeBegin_TextChanged(object sender, EventArgs e)
{
Session["TimeStart"] = txtTimeBegin.Text;
gvAvailableVets.DataBind();
// Used for debugging
lblDebug.Text = Session["TimeStart"].ToString();
}
protected void txtTimeEnd_TextChanged(object sender, EventArgs e)
{
Session["TimeFinish"] = txtTimeEnd.Text;
gvAvailableVets.DataBind();
}
I have an ASP.net with C# web app with an issue. On the app, the user can enter some data and click an "Add" button. This will generate a grid on the screen with the data the user just entered. There is also a text box for "Total Amount Requested". Below that, there is a label for "Remaining Amount". If the user puts 100.00 in the "Total Amount Requested" and then loads 75.00 into the grid, the "Remaining Amount" will show "25.00". This works fine. I added a delete row to the grid, so the user can delete specific rows. This also works. I added a _RowDeleted function to the grid, and then inserted the function to do the math for "Remaining Amount". Here is the issue:
When I delete the row, it deletes from the database, no issue. However, the label on the screen does not refresh. I put a stop in the code and walked through it. The script works, the label.text is loaded with what I expect, but it just won't refresh on screen. I've tried many different things but keep hitting a wall. Any help would be appreciated!
The Grid:
<dx:ASPxGridView ID="gridGL1" runat="server" AutoGenerateColumns="False"
DataSourceID="sdsGLData" KeyFieldName="GenLedgerID" OnRowDeleted="gridGL1_RowDeleted">
<Columns>
<dx:GridViewCommandColumn VisibleIndex="0" Caption=" " ButtonType="Button">
<DeleteButton Visible="True">
</DeleteButton>
</dx:GridViewCommandColumn>
<dx:GridViewDataTextColumn FieldName="GenLedgerID" Visible="false" VisibleIndex="1">
</dx:GridViewDataTextColumn>
<dx:GridViewDataTextColumn FieldName="UnitNumber" VisibleIndex="2">
</dx:GridViewDataTextColumn>
<dx:GridViewDataTextColumn FieldName="AccountNumber" VisibleIndex="3">
</dx:GridViewDataTextColumn>
<dx:GridViewDataTextColumn FieldName="Amount" VisibleIndex="4">
</dx:GridViewDataTextColumn>
</Columns>
<SettingsBehavior ConfirmDelete="True" />
</dx:ASPxGridView>
The SDS:
<asp:SqlDataSource ID="sdsGLData" runat="server"
ConnectionString="<%$ ConnectionStrings:FEAPConnectionString %>"
ProviderName="<%$ ConnectionStrings:FEAPConnectionString.ProviderName %>"
SelectCommand="prcRequestGLList" SelectCommandType="StoredProcedure"
DeleteCommand="delete RequestsGL where GenLedgerID = #GenLedgerID">
<SelectParameters>
<asp:Parameter Direction="ReturnValue" Name="RETURN_VALUE" Type="Int32" />
<asp:ControlParameter ControlID="lblUserID" Name="UserID" PropertyName="Text"
Type="String" />
<asp:ControlParameter ControlID="txtRequestDate" Name="RequestDate"
PropertyName="Text" Type="DateTime" />
</SelectParameters>
</asp:SqlDataSource>
The _RowDeleted
protected void gridGL1_RowDeleted(object sender, DevExpress.Web.Data.ASPxDataDeletedEventArgs e)
{
RemainingTotal();
}
The RemainingTotal():
protected void RemainingTotal()
{
TotalGLAmount();
decimal TotalReq;
decimal TotalGL;
// Total Requested Amount
if (txtTotalAmount.Text == "")
{
TotalReq = 0.00M;
}
else
{
TotalReq = Convert.ToDecimal(txtTotalAmount.Text);
}
// Total GL Amount
if (lblTotalGLAmount.Text == "")
{
TotalGL = 0.00M;
}
else
{
TotalGL = Convert.ToDecimal(lblTotalGLAmount.Text);
}
// Total Remaining Amount
if (TotalReq != TotalGL)
{
lblRemainingAmount.Text = Convert.ToString(TotalReq - TotalGL);
lblTest.Text = Convert.ToString(TotalReq - TotalGL);
if (TotalReq > TotalGL)
{
lblRemainingAmount.ForeColor = Color.Black;
}
else if (TotalReq < TotalGL)
{
lblRemainingAmount.ForeColor = Color.Red;
}
}
else
{
if (txtTotalAmount.Text != "")
{
lblRemainingAmount.Text = "<b>EVEN!</b>";
lblRemainingAmount.ForeColor = Color.Black;
lblTest.Text = "<b>EVEN!</b>";
}
else
{
lblRemainingAmount.Text = "0.00";
lblRemainingAmount.ForeColor = Color.Black;
lblTest.Text = "0.00";
}
}
}
Check these threads:
The concept of callbacks - Why is it impossible to update external control data during a callback to another control
ASPxGridView - How to update an external control during a callback
so I am running a C# function in that is supposed to change the colors of the text based on the value. When I removed the function from the list view it would output the values but when I included it, it would output nothing I have now finally figured out that there is nothing wrong with my function but with how i am binding my data to my list view, so I am wondering what is it I am doing wrong.
Here is my code:
<asp:SqlDataSource id="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:2007 SoundAssist VER 1.0.5 05-12-2011 (2013-06-24)ConnectionString %>" ProviderName="<%$ ConnectionStrings:2007 SoundAssist VER 1.0.5 05-12-2011 2013-06-24)ConnectionString.ProviderName %>" SelectCommand="SELECT [Plant], [Group No#] AS column1, [Group], [Job Code] AS Job_Code, [TWA], [Job Classification] AS Job_Classification, [Job Function] AS Job_Function, [Job Description] AS Job_Description FROM [Temp Table that contains TWA values] WHERE (([Job Description] = ?) AND ([Group] = ?) AND ([Job Classification] = ?))">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList6" Name="Job_Description" PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="DropDownList4" Name="Group" PropertyName="SelectedValue" Type="String" />
<asp:ControlParameter ControlID="DropDownList5" Name="Job_Classification" PropertyName="SelectedValue" Type="String" />
</SelectParameters>
and my list view line:
<asp:ListView id="YourListView" runat="server" DataSourceID="SqlDataSource3" OnItemDataBound="YourListView_ItemDataBound" >
And my color function:
protected void YourListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Label theTWALabel = (Label)e.Item.FindControl("TWALabel");
int theTWAValue = Convert.ToInt32(theTWALabel.Text);
if (theTWAValue >= 85)
{
if (theTWAValue < 90)
{
theTWALabel.CssClass = "YellowThis";
}
else
{
theTWALabel.CssClass = "RedThis";
}
}
}
}
And here is the List View:
<ItemTemplate>
<span style="background-color: white;color: #333333; border: 2em; border-width:1em; border-color:black;">
Plant Name:
<asp:Label id="PlantLabel" runat="server" Text='<%# Eval("Plant") %>' />
<br />
Department #:
<asp:Label id="column1Label" runat="server" Text='<%# Eval("column1") %>' />
<br />
Department Name:
<asp:Label id="GroupLabel" runat="server" Text='<%# Eval("Group") %>' />
<br />
Job Code:
<asp:Label id="Job_CodeLabel" runat="server" Text='<%# Eval("Job_Code") %>' />
<br />
TWA
<asp:Label id="TWALabel" runat="server" Text='<%# Eval("TWA") %>' />
<br />
</span>
</ItemTemplate>
Also I didn't type these in (The Sql statement I mean), I used the built in asp.net connection wizard to do this, and it created it all for me.
Edit: If there is any other info you need to help answer this question, please comment
Edit2: Is it possible that I need a if post back function?
The problem is that you are trying to access the controls in the YourListView_ItemDataBound event handler, and at that point the ListView doesn't have loaded yet.
Try adding to your ListView the event handler onLoad and inside that method then you work with your items like:
protected void YourListView_Load(object sender, EventArgs e)
{
Label theTWALabel;
int theTWAValue;
foreach (ListViewItem item in YourListView.Items)
{
theTWALabel = (Label)item.FindControl("TWALabel");
theTWAValue = Convert.ToInt32(theTWALabel.Text);
if (theTWAValue >= 85)
{
if (theTWAValue < 90)
theTWALabel.ForeColor = System.Drawing.Color.Yellow;
else
theTWALabel.ForeColor = System.Drawing.Color.Red;
}
}
}
You could try to loop through the controls rather than using FindControl.
if (e.Item.ItemType == ListViewItemType.DataItem)
{
foreach (Control c in e.Item.Controls)
{
if (c is Label && c.ID.Contains("TWALabel"))
{
Label theTWALabel = (Label)c
int theTWAValue = Convert.ToInt32(theTWALabel.Text);
if (theTWAValue >= 85)
{
if (theTWAValue < 90)
{
theTWALabel.CssClass = "YellowThis";
}
else
{
theTWALabel.CssClass = "RedThis";
}
}
}
}
}
Even if .Net modifies the ID name, you can check to see if the ID has the substring TWALabel and find your control that.
There is probably a better way to do it, but I can't think of another way that I know will work.
The YourListView_ItemDataBound method is called as the List view is being data bound. This is at the point where asp.net is creating a row in your grid for each row in your data source, so you will not be able to access the posted back data by pulling it from the control like you are doing. It is too late, as that old version of the grid has already been discarded.
I think you can either
Have the TWALabel autopostback to the server and create an OnChange event.
Parse the Request.Params to find the posted back value for each row
Try and pull what you need earlier in the page lifecycle before the databinding occurs. I think you would still have access to this data during Page_Load
I have an ObjectDataSource
<asp:ObjectDataSource SelectCountMethod="GetCount" EnablePaging="true" SortParameterName="sortExpression" ID="customersDS" runat="server" SelectMethod="GetList" TypeName="expenses.Classes.ExpenseFactory" DeleteMethod="Delete" UpdateMethod="Update" >
<SelectParameters>
<asp:ControlParameter ControlID="IdHidden" PropertyName="Value" Name="userId" />
<asp:Parameter DbType='Boolean' DefaultValue='false' Name='isExpense' />
<asp:Parameter DbType='Boolean' DefaultValue='false' Name='containRepeated' />
<asp:ControlParameter DbType="Int32" DefaultValue="" ControlID="CategorySelector2" Name="categoryId" />
<asp:ControlParameter DbType="DateTime" DefaultValue="" ControlID="FromSpentDateCalendarBox" Name="from" />
<asp:ControlParameter DbType="DateTime" DefaultValue="" ControlID="ToSpentDateCalendarBox" Name="to" />
</SelectParameters>
<UpdateParameters>
<asp:ControlParameter ControlID="IdHidden" PropertyName="Value" Name="userId" />
<asp:Parameter DbType='Boolean' DefaultValue='false' Name='isExpense' />
</UpdateParameters>
</asp:ObjectDataSource>
connected to a GridView
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
AllowPaging="True" AllowSorting="True"
DataSourceID="customersDS" CssClass="gtable sortable width100" DataKeyNames="Id"
AlternatingRowStyle-CssClass="odd" CellPadding="0" GridLines="None" OnPreRender="PreRender"
OnRowDataBound="GridView1_RowDataBound"
>
with edit and delete buttons in a CommandField
<asp:CommandField ItemStyle-Width="75px" HeaderStyle-Font-Bold=true HeaderText="<%$ Resources:Default, Actions %>" EditImageUrl="~/img/edit.png" ButtonType='Image' ShowEditButton="True" UpdateImageUrl="~/img/save.gif" CancelImageUrl="~/img/cancel.png" >
<ControlStyle CssClass="my_edit_buttons" />
</asp:CommandField>
Everything is located inside and UpdatePanel. The GridView and ObjectDataSource support and use paging. Paging works without any problems. The problem is editing. When I click edit on the first page, everything works as expected. When I click edit on the n-th item on the second or other page (greater than one), the GridView switches to the first page and selected the n-th item for editing.
(More concerete example: I switch to the second page, I select the item number 2 on that page to be edited, the GridView switches to the first page and selects the item number 2 (on the first page) to be edited).
Any ideas what may be the problem?
EDIT:
PreRender (setting GridView header):
protected void PreRender(object sender, EventArgs e)
{
try
{
GridView1.UseAccessibleHeader = false;
GridView1.HeaderRow.TableSection = TableRowSection.TableHeader;
}
catch
{
}
}
RowDataBound (changind delete button to a custom one with configmation prompt|:
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
// we are using a html anchor and a hidden asp:button for the delete
HtmlAnchor linkDelete = (HtmlAnchor) e.Row.FindControl("linkDelete");
ImageButton btnDelete = (ImageButton) e.Row.FindControl("btnDelete");
string prompt = Resources.Default.DeletePrompt;
linkDelete.Attributes["onclick"] = string.Format(prompt, btnDelete.ClientID);
Expense expense = e.Row.DataItem as Expense;
if (expense!=null)
{
if (expense.SpentDate>DateTime.Now)
{
e.Row.CssClass = "future";
}
}
e.Row.Cells[1].CssClass = e.Row.Cells[4].CssClass = "red";
}