DCSIMG
January 2009 - Posts - Zuker On Foundations

Zuker On Foundations

The realm of .NET (WPF, WCF and all around)

January 2009 - Posts

WCF – How to use client channel proxies

Note – This post does not address duplex communications, it’s not in the scope of this post.

There are many approaches you might consider while using client proxies in your solution.
Some clients might instantiate a static proxy and use it throughout the entire application lifetime, some will instantiate a proxy per needed call, etc..

Let’s define “Sequential Execution Pattern” to help me around with the describing the basic principles.

A sequential execution, as implies, is a set of calls that are invoked one right after another. Meaning the calls are made sequentially.
Note it doesn’t have to be the same thread, It could be two asynchronous operations invoked in a sequential manner.
Plus, the calls are called right after another. (without waiting for a definite time / user initiated action)

Example for sequential execution:

MyServiceClient proxy= GetNewProxy();

 

try

{

    proxy.Call1();

    proxy.Call2();

 

    proxy.Close();

}

catch { proxy.Abort(); }

Let’s get to it then..

1 - Using Using

You should not use the using directive while using proxies.

E.g.
using (MyServiceClient proxy= GetNewProxy()) { … }

The SDK comes with a sample showing exactly why you shouldn’t use it.

In essence, the dispose of the proxy calls the close which could yield an exception if the channel is faulted.
In such cases, your following code will not be executed and exceptions from inside the using statement can get masked.

The best practice of how to instantiate and dispose of the proxy is illustrated in the example above.

2 - Exceptions / Faults

If an exception is thrown out of the channel, you should dispose of the proxy and use a new one.
The channel could still be usable after exceptions, but that depends on the communication settings between the client and the server.

The best practice is to simply use a new proxy.

3 - One Way

One way operations should basically end the use of the client proxy.

Read more about it in my detailed post - WCF and OneWay – Behavioral Inconsistency

4 - Concurrent Environment 

There may be cases where the client making calls to services lives in a concurrent environment – such as a Web Application or a Service itself which acts as a client.

In such cases, you should really follow the execution pattern principle – a proxy per sequential execution.

It was discovered that in a concurrent environment, it is best to use a different proxy for a sequential execution.
You should not make several calls on the same proxy at the same time – it is proven to be bad performance-wise and you don’t really get a self-contained execution. (A call can fault the channel, causing all the other operations on the same proxy fail as well)

5 - Asynchronous Invocation

There are two types of asynchronous invocations you can do on your proxy:
a. Invoke operations asynchronously in a sequential manner. (One after the the former is completed)
b. Invoke operations asynchronously in a concurrent manner. (Execute several operations on the same proxy at the same time – concurrently)

Sequential Manner – Not much problem there, you should use the same proxy (unless an exception occurred in the former call or was it one way)

Concurrent Manner – There lies a choice.
If you make many concurrent calls – as indicated in the “Concurrent Environment” principle – you should use a new proxy instance per invocation.
If you make real few – you have the choice, you can use the same proxy instance. I rather not since I prefer a self-contained behavior. (An exception in one asynchronous operation could fault the channel and fail all your other concurrent invocations)

Basically I would suggest using a proxy per asynchronous invocation for the sake of getting self-contained behavior plus ensuring good performance if the number of the concurrent calls increases.

A problem arises when the contract at hand is a sessionful one. In that case, if the session state matters you might have to invoke the concurrent asynchronous calls on the same proxy.

Summary – Determine Execution Pattern

To summarize all of the principles above, the main guidelines are -

You should use the same proxy instance for a sequential execution while one way and Exceptions should make you re-instantiate the proxy while taking asynchronous invocations principle into mind.

A little about Sessionful Contracts

When service is set as sessionful, it should indicate that the session matters (Otherwise, you should always prefer Per Call over Per Session).

That might make you wonder though – for example, perhaps you would have to use the same instance in a concurrent environment
However, when designing sessionful contracts, you should make the usage of the service available through a sequential execution pattern alone.

You wish to preserve some sort of scalability, plus, session is limited within a timeout.

That being said, All the principles above should adhere to sessionful contracts as well.

Posted Saturday, January 31, 2009 11:42 AM by Amir Zuker | with no comments

תגים:,

WCF and OneWay – Behavioral Inconsistency

Please read the an important update here: WCF OneWay - Abort or Not

Following my last post - WCF and OneWay operations – Is OneWay really OneWay

I built up a solution that works against various sets of communication settings – different protocols and binding elements to illustrate how OneWay is inconsistent and how it might affect your code.

The source code is attached, you can download it.

I will describe my findings which address several concepts I illustrate grouped by different bindings.
If you care for the best practices alone just skip this section.

For simplicity sake, let’s assume the O/W operation on the service takes 5 seconds to complete.

Simple Execution Example:

1 IMyServiceAsync channel = Helpers.GetChannel(ChannelMode.PerCallNetTcp) as IMyServiceAsync;

2 

3 channel.DoOneWay(false);

4 channel.DoOneWay(false);

5 

6 channel.Do(false, 0);

7 

8 Helpers.CloseChannel(channel);

9 //Helpers.AbortChannel(channel);

BasicHttpBinding

The standard BasicHttpBinding works well with O/W invocations. Actually, it works just as you would expect calling O/W operations, full Fire-and-Forget behavior.

This means the O/W operations are non-blocking to the client and gets dispatched asynchronously on the service side, they do not affect consequent R/R calls and closing the channel gracefully doesn’t hang as well.

This is understandable because of the simple nature of BasicHttpBinding and its purpose.

NetTcpBinding

As some of you must know, O/W invocations simply don’t work with the standard OOTB (out of the box) NetTcpBinding.

You must enable ReliableSession if you wish to get a similiar behavior to O/W.

Following are specifics that illustrate the key issues:

  1. Simple Execution Behavior:
    Calling O/W operation right after another on the same proxy (lines 3&4 in the code) -
    The client is not blocked, however, the operations on the service side are dispatched synchronously – one after another, not something you would expect.
  2. Calling a R/R after O/W operation was called – the client will be blocked and the call will not be dispatched to service operation until ALL O/W operations are complete! (Meaning, we need to wait 10seconds until Do gets dispatched to the service operation) – Definitely not something you would expect! (don’t forget point number 1 – the O/W happen synchronously on the service)
  3. Closing the channel – acts like a R/R operation. Meaning it waits until all previous called O/W operations are complete. (In this case it wouldn’t block because the “Do” operation suffered the waiting. If “Do” hadn’t been called – CloseChannel would block for 10 seconds)
  4. Aborting the channel – you might consider that in cases where you need to invoke only O/W operations on the proxy (E.g. remove line number ‘6’ from the code), you could abort the channel and thus getting the Fire-and-Forget behavior you wish for. (Abort forcefully terminates the channel)

    Well, it’s not good. take point 1 into mind. The calls are dispatched synchronously on the service side.
    If you do abort the channel after the 2 O/W calls – the second call might not arrive to the service.
    To be more exact, if the service is set with InstanceContextMode PerCall – it will arrive, with PerSession it will not! (This is understandable though, since the session instance is gone and the call can’t be dispatched to the session instance any more)

    Obviously, your code shouldn’t rely on what was set on the service side in that matter, so it’s not recommended.
  5. Exception during O/W service invocation
    We need to distinguish between FaultExceptions which correspond to Fault messages and normal exceptions which also faults the channel.
    Throwing a fault exception from the service will not have any affect. However, throwing an exception from a O/W operation will fault the channel – if the client makes additional R/R calls to the service or tries to close the channel gracefully – blows up, an exception is thrown.

    This is obviously problematic, how would the client know whether he can reuse the channel or not? How can it know if and when exception was raised from non-blocking O/W operation? These are key issues that will be addressed later.
  6. Customize the Binding – TCP transport with OneWay binding element
    This would be preferred when O/W contracts are in place. (All operations are O/W)
    It acts just life Fire-and-Forget semantics as you might expect. Plus, no need for Reliable Session.
    However, you should note that PerSession is not supported. (each call terminates the session)

Some of these you might expect due to the nature of duplex style of communications that NetTcp possesses. But still, you want your code to work against O/W operations as it should, so bear with me :)

WsHttpBinding

The standard WsHttpBinding also behaves differently when it comes to O/W operation invocations.

In short, calling the first O/W operation doesn’t block and the code continues the execute but every other consequent call will be pending until the O/W operation completes – be it R/R, O/W, or Closing the channel.

Exceptions raised from O/W operation fault the channel as well in this case, same as NetTcp.

Summary

The behavioral inconsistency does have understandable explanations to why this might occur. However, the main goal is to write code that simply works apart from the communication chosen behind the scenes.

Best Practices

Client Side OneWay Invocation Best Practices

Fortunately, there is an invocation pattern that utilizes the Fire-and-Forget semantics for all of the modes.

(It is very similiar in concept to the basicHttp / customized tcp transport with one way binding element)

The idea is as follows – Calling O/W operation should end the use of your proxy.

In practice:

            //Not Good

            IMyService proxy1 = GetNewProxy();

            proxy1.DoOneWay(false);

            proxy1.DoOneWay(false);

            ((ICommunicationObject)proxy1).Abort();

            IMyService proxy2 = GetNewProxy();

            proxy2.DoOneWay(false);

            proxy2.Do(false, 0);

            ((ICommunicationObject)proxy2).Close();

            //Good

            IMyService proxy3 = GetNewProxy();

            proxy3.DoOneWay(false);

            ((ICommunicationObject)proxy3).Close();

            IMyService proxy4 = GetNewProxy();

            proxy4.DoOneWay(false);

            ((ICommunicationObject)proxy4).Close();

            IMyService proxy5 = GetNewProxy();

            proxy5.Do(false, 00);

            proxy5.DoOneWay(false);

            ((ICommunicationObject)proxy5).Close();

Service Design Guidelines

  1. Don’t define OneWay operations on a sessionful contract, it implies bad design. (Session matters, client should know if something happened)
    1. If you must – then set it as a terminating operation – expect & force client to create a new session after invoking O/W operations.
  2. If you managed to design O/W contracts (all operations are O/W) – prefer exposing it using a custom binding with the desired transport and a OneWay binding element.
  3. Prefer throwing FaultException instead of normal exceptions (especially in O/W operations, but a good thing in general). You might consider promoting exceptions by implementing IErrorHandler.

Note

I stated in the last post, O/W can still yield exception and block, so be aware of that. (If you follow the practice, it will be because there is an actual communication problem, not because of O/W behavior inconsistency)

Source code – feel free to download the source code and play around with it. The main samples are located in the method “OneWayShowCases” (activate a different sample as you wish).

The source code contains another part which I will discuss soon – using asynchronous invocation appropriately.

** UPDATE **:

You shouldn't abort the channel after calling O/W operation since it may prevent the service call from being accepted altogether.
Instead, you should close the channel gracefully, you should keep in mind that the 'Close' method can block, so if you care about that, I recommend using the asynchronous BeginClose/EndClose.

Posted Monday, January 26, 2009 12:51 PM by Amir Zuker | 17 comment(s)

תגים:,

WCF and OneWay operations – Is OneWay really OneWay?

Update: Read the second post about the subject: WCF and OneWay – Behavioral Inconsistency

WCF has a simple and easy way to define operations that should be made as OneWay.

You do it by setting IsOneWay = true in the OperationContract attribute.

E.g.

    [ServiceContract]

    public interface IMyServiceOneWay

    {

        [OperationContract(IsOneWay = true)]

        void DoOneWay(bool throwException);

    }

The contract contains one operation – DoOneWay which will be invoked in a “OneWay” pattern (will be discussed later).

General things you should keep in mind about OneWay operations -

  1. O/W operations must return void.
  2. O/W operations can still yield exceptions. invoking an operation on the client channel might still throw an exception if it couldn’t transmit the call over to the service.
  3. O/W operations can still block. if the service is pumped with messages and a queue had started, calling O/W operation may block your following code.

Let’s look at the following execution code:

        static void SimpleOneWayCalls()

        {

            IMyServiceOneWay oneWayChannel = Helpers.GetChannel(ChannelMode.PerCallHttp);

 

            oneWayChannel.DoOneWay(false);

            oneWayChannel.DoOneWay(false);

            oneWayChannel.DoOneWay(false);

 

            Helpers.CloseChannel(oneWayChannel);

        }

The code illustrates a simple example of creating a channel, invoking 3 O/W operations and closing the channel.

From looking at the code along with the notion of the “O/W Fire-and-Forget” semantics, one would expect the following: (Assuming the service is free to receive calls and there are no communication exceptions while transmitting the call)

  1. The 3 calls “should” be done asynchronously
    1. They should not block
    2. They should be invoked asynchronously on the service
  2. Service operation exception in a single call should not affect other calls
  3. Calling a R/R (request-reply) operation on the same channel after calling these O/W operation should not be affected and should not be blocked until the O/W operation completes
  4. Same for closing the channel – should not be blocked until the O/W operation is completed on the service side.

So.. Is that the case?

Obviously and Unfortunately – Not! (Otherwise I wouldn’t be writing this post)

The state of the channel and the affect that O/W operations might have depend upon the communication settings between the client and the server.

Actually, it is dependent on various things, mainly the transport protocol and more regarding the channel shape and binding elements – reliable session / one way binding element. Moreover, it is even affected by the InstanceContextMode which is set on your service.

Ideally, we would wish that the behavior will be decoupled from all these things.
We wouldn’t want our logical code to suffer and implement plumbing to deal with all these various kinds of different behaviors. Unfortunately, this is not the case.

I am starting to build a new project that will expose client API library, One of its goals is to provide a level of abstraction to eliminate such differences, bringing it to a single phenomenon as we would expect and doing it right.

I plan to post more details and examples about OneWay different behaviors.
Furthermore, I will discuss best practices and design guidelines regarding these things.

Posted Saturday, January 24, 2009 10:31 PM by Amir Zuker | 3 comment(s)

תגים:,

WPF Popups and ToolTip Behavior - Solution

Update 26/09/2011 - There's an updated version available in the archive 'Zuker.WpfSamples.zip' with minor bug fixes.

Finally, the last post of the series :)

Initial posts -

WPF Popups and ToolTip behavior - A Journey

WPF Popups and ToolTip Behavior – Implementation

Attached is my final solution with a working example.

Usage

<Control>
    <controls:RichToolTip.PopupContent>
        <RichToolTip>
            <TextBlock Text="This will be displayed in the popup" />
        </RichToolTip>
    </controls:RichToolTip.PopupContent>
</Control>

Dependency Properties: (Popup Placement Related)

  1. Placement
  2. PlacementTarget
  3. PlacementRectangle
  4. HorizontalOffset
  5. VerticalOffset

Properties

  1. EnableAnimation – Applies cool opening effect. (defaults to true)
  2. RelatedObject – the object the popup content was assigned to. Handy in some cases. (Check the example project)

Commands

  1. CloseCommand – Closes the opened tooltip. (You can place buttons in the RichToolTip content / contenttemplate which will invoke it in order to close it)

Attached Properties:

  1. PopupContent – The main entry point for using the RichToolTip (See usage section). you can provide any object which will be made the the tooltip content. (For being able to set placement or other properties you should insert the RichToolTip itself – see attached code)
  2. HideOnClick – A helper property for allowing a button which triggers some command to close the opened tooltip as well. I needed it – seemed useful :)

Known Issues

  1. The popup hides itself when repositioning is needed (window is moved, resize, etc..). This is the common popup behavior (Tooltip and ContextMenu themselves) so I consider this as an overall logical behavior.
  2. In XBAP mode -
    1. Transparency is set through a hack and is only supported in Full Trust mode.
    2. Moving the mouse real slowly towards the popup will cause it to hide (If it bothers you, you could modify the code and use a timer)
    3. Hovering the mouse over the associated element shows the RichToolTip even though the browser window isn’t the active window.

Posted Sunday, January 18, 2009 5:38 PM by Amir Zuker | 5 comment(s)

תגים:,

Importing blog posts using MetaBlog API

As you might have known by yesterday, I moved my blog from WindowsClient.net over here at Microsoft.co.il.

I consulted with Guy Burstein regarding how to I could import the posts to the new blog, he referred me to the following post -
Manipulate Your Blog with MetaBlog API for C#

This was a great post – thanks Guy!

I followed the steps there in order to get the API and the connection ready.

Afterwards, I connected to the source, pulled out the posts and saving them to a file.
At last, I loaded the posts, connected to the target (the new blog) and posted all the posts.

Obviously, I could do this one right after another (without persistence) but I did want to take an overall look and see everything is fine and have future reference to the posts’ content. (E.g. finding all the posts I attached files into)

Note that this does not synchronize tags nor comments.

The source code is attached, feel free to download and play with it yourself.

Posted Friday, January 16, 2009 9:04 PM by Amir Zuker | with no comments

תגים:,

Joining Microsoft Israel blogging community

Hi, This is my new blog.

I imported all the posts from my first blog which was hosed in WindowsClient.net

Stay tuned for cool stuff ;)

Posted Thursday, January 15, 2009 4:16 PM by Amir Zuker | 2 comment(s)

תגים:

LINQ to XML - XElement - Descendants vs. Elements

Someone asked me what the difference between descendants and elements is, I thought I'd post the details here for common interest.

Descendants will yield you elements of your choice from the entire source element sub-tree, whereas Elements will yield the child elements only.

E.g.

 string xml = @"
                <Root>
                    <Item>
                        <id>1</id>
                    </Item>
                    <Item>
                        <id>2</id>
                    </Item>
                    <Item>
                        <id>3</id>
                        <Items>
                            <Item>
                                <id>5</id>
                            </Item>
                            <Item>
                                <id>6</id>
                            </Item>                            
                        </Items>
                    </Item>
                    <Item>
                        <id>4</id>
                    </Item>
                </Root>";

            XDocument doc1 = XDocument.Parse(xml);

            var q1 = from e in doc1.Root.Descendants("Item")
                     select e;

            var q2 = from e in doc1.Root.Elements("Item")
                     select e;

            int c1 = q1.Count(); //6
            int c2 = q2.Count(); //4

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | 3 comment(s)

תגים:,

The MetadataExchangeClient has resolved more than MaximumResolvedReferences

This error was resulted in a specific scenario where I tried to pull a service metadata using .NET MetadataExchangeClient.

The reason was that the metadata consisted with more metadata references than the limit defined on my MEXClient instance. (The default is 10)

Solution - Increase the limit.

MetadataExchangeClient mexClient = new MetadataExchangeClient();
mexClient.MaximumResolvedReferences = MaximumResolvedReferences; //some constant

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | with no comments

תגים:,

PyBinding MarkupExtension: use Python statements for Data Binding

A very nice extension built for WPF, Read the full details Here.

E.g. -

<Polyline Points="{ln:PyBinding PointCollection([Point(p.Time,
               p.Value * $(Container.ActualHeight))
               for p in $(.MarketData.DataPoints)])}"

               Stroke
="IndianRed" StrokeThickness="1" />

Very cool!

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | with no comments

תגים:,

NDepend

I finally had the chance to look into the NDepend tool.

In short:

"NDepend is a tool that simplifies managing a complex .NET code base. Architects and developers can analyze code structure, specify design rules, plan massive refactoring, do effective code reviews and master evolution by comparing different versions of the code."

I decided to NDepend a component assembly written in our project - the output was very cool.
I was able to see the analyzing reports. There's a lot of information exposed there.

You can use that tool to extract practical development practices and potential improvements that should be made.
Moreover, you can use CQL (Code Query Language) to execute queries against the actual code and examine whatever you wish, sweet!

To sum things up, my experience with the tool had been very positive and I do see potential usage in utilizing development practices with this tool.

Very cool

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | with no comments

תגים:,

Making Ajax calls to server using PageMethods and Session_End

We were working on a project where there was used the ajax pattern of PageMethods in order to call to the server.

We experienced a weird behavior where calling the operation marked as WebMethod (required to be called as part of the PageMethods) caused weird occurrences in the Session_End global event handler.

After dwelling into it, we found that the issue was solved once we enabled the session state in the WebMethod attribute.

I thought it might be worth sharing.

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | 2 comment(s)

תגים:,

Enabling cross-domain calls for Silverlight on self-hosted WCF services

Read the full details Here.

Carlos came up with an elegant way to enable cross domain calls from silverlight to self hosted WCF service.

Such calls requires the server to allow cross site scripting which is done by placing a settings XML file in the web site root.
But what about the cases where you self host a service in a process and you're not in the context of a web site root?

Well, that's what the post is about.

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | with no comments

תגים:,

UpdatePanels, RadioButtons, UpdateProgresses and AutoPostBacks

(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

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | 6 comment(s)

תגים:,

Silverlight - Useful Posts

Read this post for great inormation about Silverlight performance tips.

Read this post for details about the Slverlight font.

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | with no comments

תגים:,

WPF Designer

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.

  1. Context-based Use
  2. Logical Validation
  3. 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!
}

Posted Thursday, January 15, 2009 3:25 PM by Amir Zuker | with no comments

תגים:,

More Posts Next page »