(or,
why my RadioButton which has AutoPostBack=”true” actually doesn’t display my UpdateProgress
or even perform a PostBack at all?!)
My fellow colleague Yitzhak Steinmetz has been playing around with Ajax capabilities and controls.
He came across some interesting scenarios, I was allowed to post his details here in my blog, so here it is:
While writing a webpage, I ran
into an interesting (gently phrased) quirk with ASP.NET AJAX.
To simplify the problem, imagine
the following scenario:
I have 2 RadioButtons, an
UpdatePanel, and an UpdateProgress on a page. The RadioButtons are outside the
UpdatePanel, but are supposed to trigger a partial PostBack of the UpdatePanel,
and of course display the UpdateProgress.
My code (relevant parts) looks
like this:
Defauls.aspx.cs
protected void Page_Load(object
sender, EventArgs e)
{
if (this.IsPostBack)
Thread.Sleep(3000);
this.lblTime.Text
= DateTime.Now.ToLongTimeString();
}
Defauls.aspx
<asp:ScriptManager ID="ScriptManager1"
runat="server"
/>
<asp:RadioButton ID="btn1" runat="server"
Text="1"
GroupName="MyGroup1"
AutoPostBack="true"
Checked="true"
/>
<asp:RadioButton ID="btn2" runat="server"
Text="2"
GroupName="MyGroup1"
AutoPostBack="true"
/>
<asp:UpdateProgress ID="MyUpdateProgress"
runat="server"
AssociatedUpdatePanelID="MyUpdatePanel">
<ProgressTemplate>
<h1>Loading</h1>
</ProgressTemplate>
</asp:UpdateProgress>
<asp:UpdatePanel ID="MyUpdatePanel"
runat="server"
ChildrenAsTriggers="false"
UpdateMode="Conditional">
<ContentTemplate>
<asp:Label ID="lblTime" runat="server" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btn1" EventName="CheckedChanged" />
<asp:AsyncPostBackTrigger
ControlID="btn2"
EventName="CheckedChanged"
/>
</Triggers>
</asp:UpdatePanel>
Run
this code and you’ll see a few unexpected behaviours:
The UpdatePanel performs a partial a PostBack only when clicking the
second RadioButton and the UpdateProgress is never displayed (even when
we do perform a partial PostBack).
Clicking
the second RadioButton, we see that after 3 seconds the time on the page chages.
If now we click the first RadioButton, nothing happens, and if we click the
second RadioButton again, nothing happens.
Removing
the Checked="true" from the first RadioButton solves the PostBack issue,
but still doesn’t display the UpdateProgress. This isn’t really a solution,
since we want the RadioButton to be checked when the page initlaly loads.
In
come smarx.com with a simple, yet annoying solution (the annoying part isn’t
their fault J):
Adding
the following code to your page (with minor relevant changes) will display the
UpdatePanel correctly (If adding this script the way it is doesn’t work, try
adding a handler for OnLoad of the <body> element and pasting it in
there):
<script
type="text/javascript">
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(function(sender, args)
{
var postBackElementID =
args.get_postBackElement().id;
if (postBackElementID == '<%=
this.btn1.ClientID %>')
{
$find('<%= this.uprogPageContents.ClientID %>').get_element().style.display
= 'block';
return;
}
if (postBackElementID == '<%=
this.btn2.ClientID %>'))
{
$find('<%= this.uprogPageContents.ClientID %>').get_element().style.display
= 'block';
return;
}
}
</script>
This
solution solves the UpdatePanel issue, but still doesn’t solve the issue with
the first RadioButton not posting back to the server.
After
much research and a few conults, the only solution I found to this issue is moving
both RadioButtons into the UpdatePanel (you can give up on the earlier
mentioned handler if you implement this).
Please
note that the second solution is needed only in the case of a RadioButton
outside of the UpdatePanel. If you have a different control outside the
UpdatePanel (a button for instance), you can leave it where it is and simply
add the script mentioned in the first solution.
I
know this solution isn’t perfect, but it’s the best I could find.
If
you can do better, please leave a comment.
P.S.
Credit
should be given to 2 posts which set me on the path to the solutions (I
recommend reading them for further understanding):
The
UpdateProgress solution
The
AutoPostBack solution
There are times in which you would have code that does some runtime work that will cause the designer to fail loading the WPF content and display the error.
At such times, you might want to tweak your code to support this need.
Let's look at the following example for a converter:
public class TemplatePickEnabledConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int id = (int)values[0];
//Do Something..
}
}
Using this converter in XAML will cause the designer to fail loading the content.
There are generally 3 ways to go about it.
- Context-based Use
- Logical Validation
- DesignMode Awareness
1) Context-based Use
The idea is to use the code dependent on the runtime environment (in this example - the converter) only when the code is basically IN the runtime environment.
There are many ways to acheive this, you can use triggers with the possibility to bound them to a static property, glue everything in runtime and what not.
2) Logical Validation
The idea is to insert some sort of validation logic.
E.g.
if
(!values[0] is int) return true;
3) DesignMode Awareness
This could be identified as a specific implementation for the first way (Context-based Use)
We could rewrite our converter to behave differently when we are in design mode.
E.g.
if
((bool)(DesignerProperties.IsInDesignModeProperty.GetMetadata(typeof(DependencyObject)).DefaultValue))
{
return true; //We're in design mode!
}
Read the full details here.
In essence:
Filestream will save the files on the filesystem giving you streaming capabities with the use of public filesytem API along with preferred performance over normal BLOB.
From the post - Rule of thumb:
Data > 256K - Consider Filestream
Data < 256K - Keep using BLOB
I have been in vacation for the last 2.5 weeks.
Myself and my Fiance in a vehicle driving around the united states.
We've done the popular route - San Francisco --> Los Angeles (Through Highway 1, Amazing!) --> Las Vegas
A lot of ruckus in that time (tech-wise), good vacation time :) I came back and noticed I have got like 150 unread blog posts to which I'm subscribed to - crazy!
It will take some time until I get a grasp upon everything.
Anyway - Some new Hotfixes!!
1) Flase C# compilation errors for ASP.NET code-behind files in VS2008 SP1 (KB957259)
Read about it here.
Get it here.
NOTE: the hotfix will only install on an SP1 or higher version of Visual Studio or Visual Web Developer Express.
This hotfix addresses the following bugs:
If you have a breakpoint in a code-behind file. On project open, you get incorrect errors in the Error List for that code-behind file (e.g. – button1 is not declared). These errors do not go away until you open that code-behind file. Once you open the code-behind file, the errors go away.
When you open a code-behind file, some false errors are shown in the Error List for a second or two and then go away.
2) Rollup Hotfix for the WPF Designer in Visual Studio 2008 SP1 (KB958017)
Read about it here.
Get it here.
NOTE: If you already have the latest version of the Silverlight Tools for Visual Studio 2008 SP1, you DO NOT need and should NOT install this hotfix. All of the fixes in the Hotfix package are already included in Silverlight Tools for Visual Studio 2008 SP1.
This hotfix addresses the following bugs:
• When a resource in an external resource dictionary is updated, Visual Studio 2008 crashes.
• WPF Designer cannot load read-only attached properties, such as the VisualStateManager.VisualStateGroups property.
• If some data is bound locally, and then the data binding is cleared, WPF designer reports an error message 'System.Windows.Data.Binding' is not a valid value for property
• WPF Designer fails to load in VS.NET 2008 SP1 (RTM) if the startup project is set to a Win32 project
• When you set and then delete the Source property of a WPF WebBrowser control, Visual Studio crashes.
• When you move a control which is using the MultiTrigger class or the DataTrigger class in the Style class, WPF Designer may throw an InvalidCastException exception.