Reputation: 919
I have a thorny little problem where I am outputting an audit trail and need to highlight the changes to each record.
I am currently using a Linq-to-Sql data source to pull the audit data back and then displaying it in a table using a repeater which works fine.
The problem is I need to change the background colour of a cell if its value has changed from the previous record and I'm struggling to find a way to do this.
An alternative I've considered is to simply generate the whole table which will work but I just get the feeling there must be an easier way to do this.
Any thoughts?
Upvotes: 2
Views: 3287
Reputation: 29
Add a hiddenfield before Repeater with a default value, compare each value with hiddenfield value for your purpose and set hiddenfield value with new value in end of repeater like this:
<asp:HiddenField ID="hf" runat="server" Value="0" />
<asp:Repeater ID="rptHistory" runat="server" DataSourceID="dsHistory">
<ItemTemplate>
<div class='time-label <%# Convert.ToDateTime(Eval("AddDate")).Date.ToString() == hf.Value ? "d-none" : "" %>'>
<span class="bg-info">
...
</span>
</div>
<div>
...
</div>
<span class="d-none"><%# hf.Value = Convert.ToDateTime(Eval("AddDate")).Date.ToString() %></span>
</ItemTemplate>
</asp:Repeater>
Upvotes: 0
Reputation: 41
I know this is an old question but to contribute to the knowledge pool and because I too found this tricky.
The declarative solution is to access the previous DataListItem
((DataList)Container.Parent).Items[Container.ItemIndex-1]
However, unfortunatly the DataItem property of this seems to be null so you cannot eval properties of the previous DataItem (for instance to perform a comparision with a property of the current DataItem).
e.g this does not work:
<%# ( DataBinder.Eval((((DataList)Container.Parent).Items[Container.ItemIndex-1]).DataItem, "SomeProperty") ) == Eval("SomeProperty") ) ? "SAME" : "DIFFERENT" %>
However, you can use the ListItem.FindControl to access a control from the previous item and access the controls contents.
(Eval("SomeProperty").ToString() == ((Label)(((DataList)Container.Parent).Items[Container.ItemIndex-1].FindControl("LabelBoundToSomeProperty"))).Text) ? "SAME" : "DIFFERENT"
Finally, a gotcha - when binding the first item there is no previous item so you will get an index out of bounds exception. As such you just have to first check that you aren't in the first item.
Putting it all togetehr gives you a final purely declarative solultion:
<%# (Container.ItemIndex==0) ? "FIRST" : (Eval("SomeProperty").ToString() == ((Label)(((DataList)Container.Parent).Items[Container.ItemIndex-1].FindControl("LabelBoundToSomeProperty"))).Text) ? "SAME" : "DIFFERENT" %>
The above will write out whether we are on the first item, or on subsequent items whether the chosen property is the SAME or DIFFERENT from that property in the previous item.
(p.s. first ever SO submission - long time reader, first time writer :)
Upvotes: 4
Reputation: 919
After must playing about I found that it was quickest to generate the html manually.
I forgot to mention in the original question that I had to reverse the order to the records (i.e. most recent first) and therefore it became even more difficult to style the record in a repeater event e.g. add first record which has to have colour coded cells to indicate changes but at this point the next record hasn't been written so you have nothing to compare against.
The easiest way seemed to be to loop through the records in the code behind and do the comparison there property to property and then to create the html with styling based on that.
Thank you to everybody who took the time to look at the question and suggest solutions.
Upvotes: 0
Reputation: 21905
Create a field in your page class:
private int previousValue;
Then in the ItemCreated or ItemDataBound event:
int currentValue = << get current value >>;
if (previousValue != currentValue) {
<< do highlight >>;
previousValue = currentValue;
}
Upvotes: 0
Reputation: 397
Select the collection of data items and save it to a class variable with a protected get property. The collection of data items needs to be keyed to the index. Then databind the GridView to the collection of data items at runtime.
Then you should be able to access the previous item in asp.net with a tag something like
<%# this.DataItems[Container.DataItemIndex] == this.DataItems[Container.DataItemIndex] ? "same as previous item" : "different than previous item" %>
Upvotes: 0
Reputation: 6825
You can use the ItemDataBound
event to check the values of the items as they're bound. At this point you can check the value against the previous cell and if it is different add a CssClass
to it that has the formatting you want.
Upvotes: 2