I have a GridView bound to ObjectDataSource. I see, the SelectMethod and the SelectCountMethod are fired twice.
In the GridView RowDataBound I have gv.ShowFooter = false;
When I comment this line, the events are fires only once. Why is that happening? How to work around it? I don't understand, why hiding one element in the databound control results is rebinding the ObjectDataSource?
RowDataBound event gets fired when GridView gets data bound (that means firing of SelectMethod).
Now, toggling properties like ShowFooter requires grid to re-create rows and it means binding the data again. That's why object data source will get triggered again.
Solution will be to set ShowFooter property earlier (instead of RowDataBound). If that's not feasible then put the logic in your object data source class to the cache the data so that you don't have to visit data store twice. For example,
// Code Behind Class
public partial class MyPage : System.Web.UI.Page
{
private object _data;
public static object SelectData()
{
// get the current page instance
var page = HttpContext.Current.CurrentHandler as MyPage;
if (null != page._data)
{
return page._data;
}
// logic to retrieve the data
...
_data = ...
return _data;
}
...
private void RefreshGrid()
{
_data = null; // force the data-source to go to database again
grid.DataBind();
}
}
Disclaimer: un-tested code only for illustration purpose
So, in above code, a static method for page code-behind is used to getting the data. And a local variable in the page class is used for caching the data. Also note for refreshing the grid, you may need to clear the variable before calling DataBind method on grid.
Related
I have a user control that is being integrated to the page on run time, now here on the page i have a few HTML control whose values need to save too, as i have written the save method logic to the user control because it has many content their to save in DB, but what i am missing is how to save the page content to the DB using the same Save Method?
If my understanding is correct, you just need to pass the values to the UC, just declare public properties in your UC and assign the values at runtime:
Check the following example:
Public properties approach
In the UC code behind
public string Street
{
get
{
return this.ViewState["c"] as string;
}
set
{
this.ViewState["c"] = value;
}
}
public void Save()
{
...
// your logic to save the UC data
// save the custom properties too, this.Street
{
In the ASPX code behind
this.myAddressTemplateControl.Street = myOtherControl.Text;
Accessing directly the page object
In the UC code behind
this.Page.FindControl("myPageControlID");
I'm trying to create my calendar control with databinding.
public partial class Calendar : UserControl
{
public static readonly DependencyProperty DateProperty =
DependencyProperty.Register("Date", typeof(DateTime),
typeof(Calendar), null);
public object Date
{
get { return GetValue(DateProperty); }
set
{
SetValue(DateProperty, value);
OnPropertyChanged("Date");
}
}
public Calendar()
{
// Required to initialize variables
InitializeComponent();
DayText.Text = ((DateTime)Date).ToString("dd");
MonthText.Text = ((DateTime)Date).ToString("MMM");
this.Loaded += new RoutedEventHandler(Calendar_Loaded);
this.GotFocus += new RoutedEventHandler(Calendar_Loaded);
}
void Calendar_Loaded(object sender, RoutedEventArgs e)
{
DayText.Text = ((DateTime)Date).ToString("dd");
MonthText.Text = ((DateTime)Date).ToString("MMM");
}
}
But When I create the listbox with this control, same calndar have the wrong date. I'm sure that the Date passed thorough databinding is correct but I don't understand why same calender show a different day (I'm noticed that is the day of a previous calendar control intance)
Thank you for supporting!
Hmm ... where do we start? Here's a few things I've noticed:
If you're using a dependency property, there's no need to call OnPropertyChanged from the Date property setter.
The dependency property declares the type as DateTime, but your public exposed property is of type object, which then requires you to cast it elsewhere.
If Calendar_Loaded is to be called in more situations than in response to the Loaded event (such as the GotFocus event, then I'd recommend that you call it something else, or create a method with a relevant name (e.g. UpdateDateParts) and call it from properly named separate event handlers.
Using fixed format specifiers when processing date strings does not localize well.
In addition to that, I'd suggest that you could implement the user interface in a manner that supports databinding (and re-templating) by using bindings and exposing the date parts of the Date dependency property instead of manually updating the Text property of some text blocks/boxes in event handlers. In fact, if you derive from Control instead of UserControl then you can create and actuall lookless control that has it's user interface defined by a style in themes\generic.xaml that can be re-defined by users of your control.
As for why the date is incorrect in different instances of your calendar control, we'd need to see some of your XAML/code to see how the control is being used and initialized to be able to provide a better answer. However, I thought the above was worth putting in an Answer, instead of trying to say it in a Comment.
I'm trying to bind a List<String> to a DropDownList in a user control. I think I'm doing the right thing, but it seems that after my code executes the bindings are cleared. Here's the code for review!
User control:
<asp:DropDownList ID="subjectNameDropDown" runat="server"/>
<asp:DropDownList ID="yearLevelDropDown" runat="server"/>
Auto-generated designed code-behind:
public partial class NewSiteMetadataUserControl {
protected global::System.Web.UI.WebControls.DropDownList subjectNameDropDown;
protected global::System.Web.UI.WebControls.DropDownList yearLevelDropDown;
}
Code-behind:
public partial class NewSiteMetadataUserControl : UserControl
{
protected override void CreateChildControls()
{
subjectNameDropDown = new DropDownList();
yearLevelDropDown = new DropDownList();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
// Attempt 1
List<String> subjectNames = GetSubjectValues();
foreach (var subjectName in subjectNames)
subjectNameDropDown.Items.Add(subjectName);
subjectNameDropDown.DataBind();
// Attempt 2
List<String> yearLevels = GetYearLevelValues();
yearLevelDropDown.DataSource = yearLevels;
yearLevelDropDown.DataBind();
}
}
Should this approach work?
If it should, how can I debug what happens after the code executes?
Yes, this approach should work, here's why it currently isn't,
A DropDownList done with DataBind needs a DataSource. This is why Attempt #1 is not working.
If you're binding to a List<string>, there is no clear key/value pair to bind to. This is why when binding to a List<Person> (for example), you need to override .ToString() in the Person class to provide the key/value binding, or manually set the DataTextField, DataValueField.
There is no way for ASP.NET to work out a key/value pair for a string.
Think about what HTML you want. What should be the key/value for a simple string? Doesn't make sense does it.
Since you don't really care about the "key" (only what is displayed), i suggest you bind to a Dictionary<TKey,TValue> instead.
Either make your method return that, or iterate through the list and add them to the dictionary with an index.
The problem here was CreateChildControls. Somewhere in my attempts to make this work I added this method that initialises the controls. This isn't necessary and in fact caused the data bindings to be wiped out, as it was automatically called by the framework after OnLoad.
The solution was to remove this method and the call to EnsureChildControls.
I have an ASP.NET 3.5 GridView on a WebForm.
The GridView gets data from an ObjectDataSource which is set via the DataSourceID property in the code in front.
The ObjectDataSource returns a List of custom data class objects (just a class with public properties) to populate the GridView.
What I want to do is use the a List comsumed by the GridView in another code-behind method. At a high level:
1. GridView is loaded with List data from ObjectDataSource.
2. In the GridView.OnDataBound method I call GridView.DataSource to get the List object.
3. I enumerate the List and use the same data to do some other operation.
The theory being one less duplicated method call and one less call to the back-end database.
I've tried calling DataSource from the GridView' DataBound method and calling GridView.Rows[x].DataItem. In each case I only get a Null reference exception ("Object reference not set to an instance of an object").
Is there any way to achieve what I'm after?
If I understand you correctly, you want the OnRowDataBound event. This way, you can use data from the row that was just databound:
protected void gvGrid_RowDataBound(object sender, GridViewRowEventArgs e)
{
CustomDataClass data = e.Row.DataItem as CustomDataClass;
if (data != null)
{
// access data here...
}
}
But do you want the onRowDataBound event? It looks like you want the onDataBound event for the GridView's entire datasource...
So you don't necessarily want one instance (row) of CustomDataClass, you want the entire CustomDataClass[] array of rows to use somewhere else.
HELP! I need this too.
******UPDATE******
I found the answer. Do this as below and set the OnSelected event in your objectdatasource:
protected void ObjectDataSource_Selected(object sender, ObjectDataSourceStatusEventArgs e)
{
ObjectListRow[] objectArray = (ObjectListRow[])e.ReturnValue;
List objectList = objectArray.ToList();
}
It turns out my datasource was an array, but if yours is a List<> then just cast the e.ReturnValue as the List.
EASY CHEESY.
I'm not clear about this....
When having a gridview on the View, is the controller who has to set up the Data source, columns, etc? or I just have to expose the DataBinding stuff, fire it from the controller and let the html/codebehind on the view handle all the rendering and wiring up?
To be more precise: on the view should I have
private GridView _gv
public _IList<Poco> Source {
get {_gv.DataSource;}
set {_gv.DataSource = value;
_gv.DataBind();}
}
Or should it be (from MVP pattern - Passive View and exposing complex types through IView (Asp.Net, Web Forms))
private GridView _datasource;
public DataSource
{
get { return _datasource; }
set
{
_datasource = value;
_datasource.DataBind();
}
}
Maybe I'm having it all wrong ....
Where can I find an example that is not a "Hello world" example on MVP for ASP.Net???
Your controller should be in charge of setting the "result" of the databinding. The view is in charge of displaying it propertly.
So for example, your webform/usercontrol (View) could have the data source exposed as an object property that your View should know how to handle when it receives it:
public MyObject DataSource
{
set
{
_datasource = value;
_datasource.DataBind();
}
}
So if you need to have an ItemDataBound event, I would still handle it in the view. Even though there could be business logic in the event. If you need to have business logic in the event, I would put it in the MyObject result before it is passed to the view.
So an example would be to have a property of "MyObject" be "AllowDelete" and in your ItemDataBound, the value of this property determines if a column in the GridView is enabled or not.
Having just listened to a recent Hanselminutes on this topic, it might be worth having a look at the http://webformsmvp.com/ project, which seems to bring a bit of rigidity into separating concerns within WebForms.