Xaml Mammal Presentation Notes

Initial Meeting Notes and code:

Xs.Code for WPF

<Button Click="HandleClick"
        Name="TestButton"
        Width="50"
        Height="30"
        Content="Click Me!" />

<x:Code>
            
void HandleClick(object sender, RoutedEventArgs eventArgs)
{
    TestButton.Width = 100;
    TestButton.Content = "Thank you!";
    MessageBox.Show("Hello from Xaml");
}
      
</x:Code>

Links

Xaml Intellisense Presenter

Xaml Styler

buildwindowscontest.com

Silveright Lifespan

Share

.Net Regex: Can Regular Expression Parsing be Faster than XmlDocument or Linq to Xml?

iStock_000017256683XSmallMost of the time one needs the power of the xml parser whether it is the XmlDocument or Linq to Xml to manipulate and extract data. But what if I told you that in some circumstances regular expressions might be faster?

Most conventional development thinking has branded regex processing as slow and the thought of using regex on xml might seem counter intuitive. In a continuation of articles I again want to dispel those thoughts and provide a real world example where Regular Expression parsing is not only on par with other tools in the .Net world but sometimes faster. The results of my speed test may surprise you;  and hopefully show that regular expressions are not as slow as believed, if not faster!

See: Are C# .Net Regular Expressions Fast Enough for You?

Real World Scenario

There was a developer on the MSDN forums who needed the ability to count URLs in multiple xml files. (See the actual post count the urls in xml file on Msdn) The poster received three distinct replies, one to use XMLDocument, another provided a Linq to XML solution and I chimed in with the regular expression method. The poster took the XMLDocument method and marked as the answer, but could he have done better?

I thought so…

So I took the three replies and distilled them down into their core processing and wrapped them in a similar IO extraction layer and proceeded to time them. I created 48 xml files with over one hundred thousand urls to find for a total of 13 meg on disk. I then proceeded to run the test all in release mode to get the results.  (See below section Setup to get a gist repository of the code).

Real World Result

Five tests, each test name is the technology and the user as found on the original msdn post. In red is the slowest and fastest time. Remember XmlDoc is the one the user choose as the answer.

Test 1
Regex           found 116736 urls in 00:00:00.1843576
XmlLinq_Link_FR found 116736 urls in 00:00:00.2662190
XmlDoc_Hasim()  found 116736 urls in 00:00:00.3534628

Test 2
Regex           found 116736 urls in 00:00:00.2317883
XmlLinq_Link_FR found 116736 urls in 00:00:00.2792730
XmlDoc_Hasim()  found 116736 urls in 00:00:00.2694969

Test 3
Regex           found 116736 urls in 00:00:00.1646719
XmlLinq_Link_FR found 116736 urls in 00:00:00.2333891
XmlDoc_Hasim()  found 116736 urls in 00:00:00.2625176

Test 4
Regex           found 116736 urls in 00:00:00.1677931
XmlLinq_Link_FR found 116736 urls in 00:00:00.2258825
XmlDoc_Hasim()  found 116736 urls in 00:00:00.2590841

Test 5
Regex           found 116736 urls in 00:00:00.1668231
XmlLinq_Link_FR found 116736 urls in 00:00:00.2278445
XmlDoc_Hasim()  found 116736 urls in 00:00:00.2649262

 

Wow! Regex consistently performed better, even when there was no caching of the files as found for the first run! Note that the time is Hours : Minutes : Seconds and regex’s is the fastest at 164 millseconds to parse 48 files! Regex worst time of 184 milleseconds is still better than the other two’s best times.

How was this all done? Let me show you.

Setup

Ok what magic or trickery have I played? All tests are run in a C# .Net 4 Console application in release mode. I have created a public Gist (Regex vs Xml) repository of the code and data which is actually valid Git repository for anyone how may want to add their tests, but let me detail what I did here on the blog as well.

The top level operation found in the Main looks like this where I run the tests 5 times

Enumerable.Range( 1, 5 )
            .ToList()
            .ForEach( tstNumber =>
            {
                Console.WriteLine( "Test " + tstNumber );
                Time( "Regex", RegexFindXml );
                Time( "XmlLinq_Link_FR", XmlLinq_Link_FR );
                Time( "XmlDoc_Hasim()", XmlDoc_Hasim );
                Console.WriteLine( Environment.NewLine );
            }

while the Time generic method looks like this and dutifully runs the target work and reports the results in “Test X found Y Urls in X [time]”:

public static void Time<T>( string what, Func<T> work )
{
    var sw = Stopwatch.StartNew();
    var result = work();
    sw.Stop();
    Console.WriteLine( "\t{0,-15} found {1} urls in {2}", what, result, sw.Elapsed );
}

Now in the msdn post the different methods had differing ways of finding each xml file and opening it, I made them all adhere to the way I open and sum the ULR counts. Here is its snippet:

return Directory.EnumerateFiles( @"D:\temp", "*.xml" )
            .ToList()
            .Sum( fl =>
            {

            } );

Contender  –  XML Document

This is one which the poster marked as the chosen one he used and I dutifully copied it to the best of my ability.

public static int XmlDoc_Hasim()
{
    return Directory.EnumerateFiles( @"D:\temp", "*.xml" )
                .ToList()
                .Sum( fl =>
                {
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml( System.IO.File.ReadAllText( fl ) );

                    if (doc.ChildNodes.Count > 0)
                        if (doc.ChildNodes[1].HasChildNodes)
                            return doc.ChildNodes[1].ChildNodes.Count;

                    return 0;

                } );

}

I used the sum extension method which is a little different from the original sum operation used, but it brings the tests closer in line by using the Extension.

Contender – Linq to Xml

Of the other two attempts, this one I felt was the more robust of the two, because it actually handled the xml namespace. Sadly it appeared to be ignored by the original poster. Here is his code

public static int XmlLinq_Link_FR()
{
    XNamespace xn = "http://www.sitemaps.org/schemas/sitemap/0.9";

    return Directory.EnumerateFiles( @"D:\temp", "*.xml" )
                    .Sum( fl => XElement.Load( fl ).Descendants( xn + "loc" ).Count() );

}

Contender – Regular Expression

Finally here is the speed test winner. I came up with the pattern design Upon by looking at the xml and it appeared one didn’t need to match the actual url, but just the two preceding  tags and any possible space between. That is the key to regex, using good patterns can achieve fast results.

public static int RegexFindXml()
{
    string pattern = @"(<url>\s*<loc>)";

    return Directory.EnumerateFiles( @"D:\temp", "*.xml" )
                    .Sum( fl => Regex.Matches( File.ReadAllText( fl ), pattern ).OfType<Match>().Count() );

}

XML1 (Shortened)

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>http://www.linkedin.com/directory/companies/internet-web2.0-startups-social-networking/barcelona.html</loc><changefreq>weekly</changefreq></url>
<url><loc>http://www.linkedin.com/directory/companies/internet-web2.0-startups-social-networking/basel.html</loc><changefreq>weekly</changefreq></url>
<url><loc>http://www.linkedin.com/directory/companies/internet-web2.0-startups-social-networking/bath.html</loc><changefreq>weekly</changefreq></url>
<url><loc>http://www.linkedin.com/directory/companies/computer-networking/sheffield.html</loc><changefreq>weekly</changefreq></url>
<url><loc>http://www.linkedin.com/directory/companies/computer-networking/singapore.html</loc><changefreq>weekly</changefreq></url>
<url><loc>http://www.linkedin.com/directory/companies/computer-networking/slough.html</loc><changefreq>weekly</changefreq></url>
<url><loc>http://www.linkedin.com/directory/companies/computer-networking/slovak-republic.html</loc><changefreq>weekly</changefreq></url>
</urlset>

Xml2 Shortened

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url><loc>http://www.linkedin.com/groups/gid-2431604</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2430868</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/Wireless-Carrier-Reps-Past-Present-2430807</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2430694</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2430575</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2431452</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2432377</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2428508</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2432379</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2432380</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2432381</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2432383</loc><changefreq>monthly</changefreq></url>
<url><loc>http://www.linkedin.com/groups/gid-2432384</loc><changefreq>monthly</changefreq></url>
</urlset>

Summary

It really comes down to the right tool for the right situation and this one regex really did well. But Regex is not good at most xml parsing needs, but for certain scenarios it really shines. If the xml has malformed or the namespace was wrong, then the parser has its own unique problems which would lead to a bad count. All the technologies had to do some upfront loading and that is key to how they performed. Regex is optimized to handle large data efficiently and as long as the pattern is spot on, it can really be quick.

My thought is don’t dismiss regular expression parsing out of hand, while the learning of it can pay off in some unique text parsing situations.

Share

Tags: , ,

C# Silverlight: Codebehind Binding Between Two Controls Example

Here is a quick example of binding between two controls on the same xaml page. I have provided both ways of doing the binding the first in xaml and the second in the code behind. The first example is the most common method of binding in xaml while the other is the code behind, a more dynamic binding situation. 

Sometimes it helps to see a contrast if one is used to one or the other, a translation of sorts; so here it is:

Xaml Binding

The goal is to have the custom Slidebox control’s Spacing property to be bound to the TickTrack Control’s SpacingMargin property since these two controls have to work together (think of a slider control on a timeline).

If one were to do this in xaml it would look like this

<my:TickTrack
    x:Name="tkTrack"
    SecondsEnd="{Binding SecondsEnd, ElementName=userControl}"
    SecondsStart="{Binding SecondsStart, ElementName=userControl}"
    TickFrequency="{Binding TickFrequency, ElementName=userControl}" 
    HorizontalAlignment="Left" Width="{Binding Width, ElementName=userControl}" Height="59" Canvas.Top="70" />

<my:SlideBox Spacing="{Binding SpacingMargin, ElementName=tkTrack}"  />

The slidebox spacing is now uses the named tkTrack control’s dependent property  (not shown but publicly available property on TickTrack).

Code Behind Binding

If one were to do the same in code behind, say for a dynamically created custom slidebox control:

var bndSpacing = new Binding() 
                    { 
                        Source = tkTrack, // Not the name but actual instance object
                        Path = new PropertyPath( "SpacingMargin" ) 
                    };

var sb = new SlideBox();

// "{Binding SpacingMargin, ElementName=tkTrack}"
sb.SetBinding( SlideBox.SpacingProperty,
               bndSpacing );

We create a binding instance with  the actual source and the path setup similar to xaml but different. The Source is not a named source but the actual object for the source to be bound to. Once we have the object, we then specify that the new slide box instance is to set the binding to the SpacingProperty (of the class description) dependency property of the slidebox instance.

Hope This Helps

Share

Tags: , ,

Fear and Loathing in Windows 8 with the Acer ICONIA 6120 Dual-Screen Touchbook

Windows 8 experience on top panel with Windows 7 visual experience on the lower touch panel.

As of 11/11/2012 Acer does not support the Iconia 6120 for windows 8 either by its Windows upgrade assistant or via any downloads for the notebook in its support section. All drivers are a year old and only for Windows 7. Windows 8 can be installed and it works, but the lower screen, nor the specialized keyboard button (on the side of the laptop) does not bring up the keyboard. Making the tablet ineffective as a Windows 8 platform.

I recently began my Windows 8 journey by installing the developer preview on an Acer Iconia 6120 or more commonly know as the dual touch screen laptop or touchbook as they have named it. My goal is to learn the metro style programming and experience the wave of the future in application development on tablet and smaller items. I am primarily a C# Silverlight developer so it is fundamental that I understand exactly what the pro’s and con’s of creating applications to the next version of windows will entail. The following are some of my initial thoughts on what I have run into as I have begun this journey which can be read by developers and non developers alike.

Souping up the TouchBook

I had purchased the Acer off of Ebay from a company which claimed they used differing laptops for demos for roughly a week, no more than ten hours of usage promised, and would sell them in a non new condition.. Long story short is that I didn’t have to pay MSRP on this gem so technically its used, but that is fine for my purposes.

There are many reasons purchasing this Touchbook which I will speak to, but the primary was for its cool factor of dual touch screens.  But I must admit that while waiting for shipment (which was delayed for a week unbeknownst to me from the seller (grrr)) my loathing began to take hold. I wondered if the dual screens would be functional within Windows 8 and thus would end up being a nice door stop for a future unknown open door draft choice in my house?Rating 4.2, Intel Core I5 M480 @2.67ghz, 4 GB of ram on 64bit OS with 10 touch points.

I also knew that Acer ships it with a Windows 7, so the possibility of bricking both screens felt remote and that the tablet is up to Microsoft’s specs for the minimum for Windows 8 screen resolution wise was 1024×768 and the screens on the Iconia are both 1366×768.

On the downside one of coolest features found on the Iconia would probably not be there on Windows 8. That feature is where a user places his or her palms (see virtual keyboard) on the lower screen, hence bringing up Acer’s full sized virtual keyboard and yes it did not come over for Windows 8. As of this writing I am still unaware of how to get the target software to bring up Acer’s virtual keyboard which does come up in the bios actually. THe windows virtual keyboard does make its appearance as designed for Windows 8 albeit smaller form factor than the Inconia’s. Sad smile

The machine I choose had to be one where I could actively develop upon it and had to have more horse power than most of the tablets out there and the Acer fit that bill for dual usage. The fact that it came with an Intel Core I5 chip with four gig of ram meant that I could develop metro apps on Visual Studio 2011 preview, which requires 64bit at this time, and have a peppy machine to boot.

Alright you ask, what did you do to soup it up?

Once I got the laptop, I took off the backing panel of the Acer and removed it’s 640 gig Western Digital (5400 rpm) hard drive and gave it some real power with a Kingston SSDNow V+100 solid state drive. Its capacity is only 96 gig which is fine for a development machine to hold the OS and tools. I actually have one it in my primary work machine, a Dell XPS 17 Core I7 laptop, which I use on a daily basis, so it was a no brainer to use the Kingston again for the Acer. The above windows experience of 4.2 with the SSD is no barn burner it really does the job.

 

My Touching Windows 8 Experience

Now it is obvious that Microsoft has an Alpha version on their hands here but frankly the experience has been anything as such. I have yet to blue screen or have any major problems. It is apparent that Windows 8 builds off of Windows 7 for all drivers I have installed have installed without problems. The following are the problems or situations I have encountered using the Dual screen

Extended Windows Not Behaving as Expected
  1. Since the Acer is a Frankenstein dual screen tablet and a single screen the OS wants to treat the lower screen as just an extension of the top screen and it just doesn’t flow right.
    1. Only one screen is the full Windows 8 experience while the other screen is always the Windows 7 experience. When both screens are the seven experience, when dragging a window by touch to the lower window, the non touch area stops the window and the menu bar (the part which needs to be touched to have it moved) is stuck in the upper window and there is no way to flick it down to the lower window and a mouse must be used instead.
    2. Touching the lower screen also sends touch notifications to the upper screen. I believe this is a bug and hopefully will be fixed in upcoming versions.
  2. When working with a third screen attached from the HDMI port there is no way to have all three screens active in any configuration. So I have had to leave off the bottom screen when I work with an external monitor. The situation is shown below in the screen shots when trying to get all of them to work. The left picture shows the Iconia running with both screens while the right screen show s the monitor configuration I have to deal with while having the lower Iconia screen inactive. (Note even though the lower screen is inactive when using the other monitor the touch is still active on the screen and its actions are sent to the upper screen. Big bug.)
    Top and bottom of the laptop are enabled while the external monitor is disabled. The lower touch screen is disabled for the windows to work.
General Observations
  1. Most of the default Metro apps do not work on either of the Iconia’s screens! One touches them, the title splash screen comes up and eventually a blank screen of the default background color of the apps tile is shown. This situation, not related to the Iconia, has been reported to Microsoft (see When I click on an application tile, nothing happens. How can I launch the Metro applications?) and the answer was that the apps were running in less than 1024×768 resolution. For the Iconia this is not the case and should exceed that threshold by being 1366×768. In summary:
    1. Most apps fail on the Iconia’s screens and do not properly load.
    2. Most apps run on the third connected screen when the Windows 8 experience is brought to It.
    3. No error message is shown to the user.
    4. Developed apps (at least the few I have done), using the developer preview of Visual Studio 2011 work on the touch experience.
  2. Windows 8 doesn’t play well with non touch monitors. Sometimes the Windows 8 experience jumps on to the monitor and the program is expecting touch (?) actions and one has to force the windows 7 experience back to the monitor.
  3. IE 10 sometimes incorrectly reports a URL of another tab than the page being viewed when multiple tabs are being used.
  4. No Aero experience with Windows Key-Tab under W7 experience and if done under the W8 experience it is a single view change.
  5. Microsoft Virtual Keyboard needs to adapt to larger screens to give the full keyboard effect. The slimmed keyboard is frustrating to use when typing in passwords with numbers or symbols and one has to click over to show a different layout. If the screen real estate is available why not use it, or at least allow the user to configure it.

Summary

The touch experience of Windows Eight is still a long way off from being a reality. Frankly there needs to be a way to lock the experience of Windows 8 or Windows 7 to certain screens depending on the screens needs. It is a nice to have in certain situations say a true tablet experience, but the laptop or touch screens will want the older Windows 7 experience for the most part. I suspect that need to be accommodated by Microsoft as the versions evolve over time. So far I can use the Acer Iconia 6120 for my development purposes, but a true stand alone Windows 8 platform it is a long way off from being a useful stand alone experience.

Share

Tags: ,

Effective Silverlight 5

This is related to my presentation tonight (July 25, 2011) at the Denver Visual Studio User’s Group on Effective Silverlight 5 Development.

Links

 

RitchTextBox OverflowContentTarget Example

<StackPanel Width="400"
            VerticalAlignment="Top"
            Orientation="Horizontal">

    <RichTextBox x:Name="rtbPrimary"
                 Width="80"
                 Height="100"
                 Margin="5,10,0,0"
                 HorizontalScrollBarVisibility="Disabled"
                 VerticalScrollBarVisibility="Disabled"
                 OverflowContentTarget="{Binding ElementName=rtbOverflow}">
        <Paragraph>
            The Denver Visual Studio User's group is overflowing at 100 people! Come early to get a seat.
        </Paragraph>
    </RichTextBox>

    <RichTextBoxOverflow Width="200"
                         Height="100"
                         Margin="5,10,0,0"
                         HorizontalScrollBarVisibility="Disabled"
                         VerticalScrollBarVisibility="Disabled"
                         x:Name="rtbOverflow" />

</StackPanel>

HTML 5 Canvas

<!DOCTYPE html>
<title>Canvas Shapes and Sizes</title>
    <script type="text/javascript">
        window.onload = function () {
            var canvas = document.getElementById('cvPrimary');
            var ctx = canvas.getContext("2d");

            //Draw a rectangle
            ctx.fillStyle = 'Red';
            ctx.fillRect(10, 20, 50, 50);

            //Draw a circle
            ctx.arc(50, 150, 50, 0, 2 * Math.PI, false);
            ctx.fillStyle = 'Green';
            ctx.fill();

            //Draw an arc
            ctx.beginPath();
            ctx.arc(80, 280, 50, 0, Math.PI, false);
            ctx.fillStyle = 'Navy';
            ctx.fill();

            //Draw lines
            ctx.beginPath();
            ctx.moveTo(50, 350);
            ctx.lineTo(0, 450);
            ctx.lineTo(100, 450);
            ctx.lineTo(50, 350);
            ctx.strokeStyle = 'Orange';
            ctx.lineWidth = 4;
            ctx.stroke();
            ctx.fillStyle = 'Yellow';
            ctx.fill();
        };
</script>

<canvas id="cvPrimary" width="800" height="600"/>

Siverlight Extension

<navigation:Page xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
           x:Class="EffectiveSilverlight.Views.ExtensionOverview"
           xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
           xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
           xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
           xmlns:dvsug="clr-namespace:EffectiveSilverlight.Views"
           mc:Ignorable="d"
           xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
           d:DesignWidth="640" d:DesignHeight="480"
           Title="ExtensionOverview Page">
    <StackPanel>
        <sdk:Label Margin="10,10,0,0"
                   FontSize="14"
                   FontFamily="Georgia"
                   FontWeight="Bold"
                   Content="{dvsug:DenverVSUG}"
                    />
    </StackPanel>
</navigation:Page>

 

using System.Xaml;

namespace EffectiveSilverlight.Views
{
    public class DenverVSUGExtension : IMarkupExtension<string>
    {

        public string ProvideValue(IServiceProvider serviceProvider)
        {

            return "88 people saw William Wegerson discuss Effective Silverlight";

        }

    }
}
Share

C# Silverlight WCF: Thread Safe Multiple Async Call Strategy With Final Operation To Join Data.

Seven Pointing Arrows ending at different points except one arror leaping of the page to show the final Async call.This article describes one way to handle asynchronous or async calls in .Net 3.5 or .Net 4.0 when using WCF in Silverlight in C#. The goal is to have a final operation wait for all the calls to finish so to combine all the data gathered, all in a thread safe way. A secondary goal is to minimize the consumer code required to perform this operation from what is currently available in straight WCF async calls.

This article has a short shelf life because after .Net 4 (see What’s Next in C#? Get Ready for Async!) one will use the built in Asynchrony methodology developed. Until that time if one is using any version of Silverlight and WCF then this article describes how to handle those multiple async calls and join the data in a final method call.

Final Result Example

Before delving into the solution, here is how the consumer will use the methodology. Below a user is getting account information of user requests, departments and accounts to join all the data on the view model in the final method for display on a Silverlight page. Thesee operations as shown are setup when the view model class (MyViewModel) is created and no blocking occurs keeping UI thread clear.

public MyViewModel()
{
    DataContext = new MyServiceClient();

    FinalAsync(CombineDataAndDisplay); // When all the data is retrieved, do this method to combine the data From the 3 async callls below

    // Provide the operation as a lambda (could be a method call) to assign data to our target backing store property
    // and if all has gone well (no errors in other async calls) and it is the final completing operation. Do the final
    // Processing call automatically.
    DataContext.GetUserRequestsCompleted   += (s, e) => { AssignResultCheckforAllAsyncsDone(e, e.Result, ref _UserRequests, "Acquisition failure for User Requests");};
    DataContext.GetAccountsCompleted       += (s, e) => { AssignResultCheckforAllAsyncsDone(e, e.Result, ref _Accounts, "Acquisition Failure for Accounts"); };
    DataContext.GetDepartments             += (s, e) => { AssignResultCheckforAllAsyncsDone(e, e.Result, ref _Departments, "Failed to get Department Info."); };   

    // Start the Async processes 
    MultipleAsyncRun(DataContext.GetUserRequestsAsync);
    MultipleAsyncRun(DataContext.GetAccountsAsync);
    MultipleAsyncRun(DataContext.GetDepartmentsAsync);

    // Exit out and return the UI thread to the user operations.
}

// Once all the data is done, combine and assign into our
// PagedCollectionView property for display on the screen.
public void CombineDataAndDisplay()
{
    // Combine missing data on the calls
   _UserRequests.ToList()
                .ForEach(ur =>
                {
                ur.BillingName     = _Accounts.First(ac => ur.AccountID == ac.AccountID).Name;
                ur.DepartmentName  = _Departments.First(dp => dp.DepartmentID == ur.DepartmentID).Name;
                });


    UserRequests = new PagedCollectionView( _UserRequests);
    UserRequests.GroupDescriptions.Add(new PropertyGroupDescription("DepartmentName"));

}
Explanation
Line  5: The final async call is where this process specifies a method to use after all async calls are completed. On line 24 of the example is our final operation method to do that which is reported to FinalAsync.
Line 11-13: Just like the normal async process we subscribe to the anync handler but we handle it in a anonymous lambda.
Line 11-13: AssignResultCheckForAllAsyncsDone method will check the result returned, code show later in the article. All one needs to know now is that the respective _UserRequests, _Accounts and _Departments, all backing store variables (not properties) will be loaded with the data if the result information ( e ) operation contains no errors. This method does all the heavy lifiting by checking error state, loading the data variable, decrementing the async count and firing off the final method if all asynchronous operations are completed.
Line 16-18: Just like the normal WCF async process we must launch the asnc calls and these statements do just that. We supply the method to be launched inside the MulipleAsync method.
Line 24: Here is our final method to be executed once the asynchrony process is complete. This method combines all the async data internally into the _UserRequest object at which it becomes complete and can be used.
Line 34: Finally a paged collection view is created from our data to be bound to Silverlight Xaml items which is our end result.
24-37: Note: The section below has a variable entitled AsyncErrors. The above example did not check that for null or an error situation. I have left out the check of AsyncErrors for brevity of the example. See the last section for an example of proper error handling.

Multiple Async Methodology Plumbing

Below is what will needed to be brought into your View Model, or placed on your page if not using MVVM. This is where the .Net thread safe Silverlight asynchronous operations will occur.

// Lock Objects 0 for false, 1 for true.
private int AsyncErrorResource = 0;
private int AsyncFinal = 0;

private List<Exception> AsyncErrors;  // If not null errors have been encountered.

private int PendingAsyncOperations; // Holds the counted total of ongoing async operations. Zero means do users final operation.

private Action FinalOperation;      // The user's final operation.

public void MultipleAsyncRun(Action Operation)
{
    Interlocked.Increment(ref PendingAsyncOperations);
    Operation();
}

public void FinalAsync(Action method)
{
    FinalOperation = method;
}

public void AssignResultCheckforAllAsyncsDone<T>(AsyncCompletedEventArgs ea, T receivedData, ref T assignTo, string ErrorMessage)
   where T : class
{
    bool valid = !((ea.Error != null) || (receivedData == null));

    if (valid == false)
    {
        if (0 == Interlocked.Exchange(ref AsyncErrorResource, 1))
        {
            if (AsyncErrors == null)
                AsyncErrors = new List<Exception>();

            AsyncErrors.Add(ea.Error);

            //Release the lock
            Interlocked.Exchange(ref AsyncErrorResource, 0);
        }
    }
    else
    {
        assignTo = receivedData;
    }

    Interlocked.Decrement(ref PendingAsyncOperations);
    if (PendingAsyncOperations == 0)
    {
        if (0 == Interlocked.Exchange(ref AsyncFinal, 1))
        {
            FinalOperation();
        }

        Interlocked.Exchange(ref AsyncFinal, 0);
        Interlocked.Decrement(ref PendingAsyncOperations); // Move to -1
    }
}
Explanation
Line  2/3: These variables are used as a lock targets for thread safety. Value zero means its open and a value of 1 means a lock is in place.
Line  5: Any errors encountered are placed into AsyncErrors. The final operation must check this variable. If it is not null errors have occurred and data is incomplete see the final section of this article on how to handle errors.
Line 7: This variable will hold the running total async operations. Once it gets to zero the final operation will be executed.
Line 11: This method counts and stores our async operations as they come in and launches the async method as well.
Line 13: This process uses the Interlocked class found in the System.Threading namespace. To quote Microsoft, “Provides atomic operations for variables that are shared by multiple threads. “. We simply count up the PendingAsyncOperations variable. Later when the operations complete this will be decremented.
Line 18: This method is called by the consumer so we know what method to launch when all async operations have completed. We assign the method to a holder variable as found on line 9.
Line 22: This method will take in the event arguments and check if there is a problem. It will store the error if there is one and also decrement our count. If our count hits zero it will launch the users final operation.
25-39: Checking errors reported by the async call. If there are any we log them and do not assign the variable. Note whether an error exists or not the operation continues below where the final operation is checked for and executed. Its up to the final operation to check if errors exists and handle them appropriately.
Line 42: If the event reports a success this is where we assign the value to the passed in reference to the template T assignTo. If one doesn’t use a variable for assignTo reference an exception will be generated on this line. See the following section as to why. 
Line 46: We safely decrement our operations count variable. Zero means we are done!
Line 47-57: Here is where we execute the final operation when the count is zero. Note there is an extra lock if operations unlikely hit a zero at the same time. The extra lock ensures only one will execute the final method.

That is it, simply use the above code and you can have all your operations work done asynchronously. Smile Now for the disclaimers…

Why Can’t Properties be Used by AssignResultCheckforAllAsyncsDone?

We must use direct variables like in our example

private ObservableCollection<UserRequestDTO> _UserRequests;
private ObservableCollection<Account> _Accounts;
private ObservableCollection<Department> _Deparments;

// Not Private ObservableCollection<Department> _Departments { get; set; }

If one used a property this exception is thrown.

A property, indexer or dynamic member access may not be passed as an out or ref parameter

That is because we are using the generic method AssignResultCheckforAllAsyncsDone to assign a value, and that assignment has to have an exact object instance for the template (T) object and not a Property to assign the value. If your end result is in a property, simply assign it from the variable to the property in the final async call.

Handling Errors

Simply check the error variable if it is not null it has encountered errors.

if (AsyncErrors != null)
{
    MessageBox.Show("Errors: " + string.Join(string.Format("{0}{0}", Environment.NewLine), AsyncErrors.Select(ex => ex.Message)));
}
else
{
    // Success Handle accordingly.
}
Share

Tags: , , , ,

C#: Finding List Duplicates Using the GroupBy Linq Extension and Other GroupBy Operations and Usage Explained

Woman against mirror showing her reflection as she seductively looks outward from picture. Her reflection is like a duplicate found in a list.
When one is dealing with lists such as strings there can be a situation where duplicates can be encountered and one such way of finding identical strings is to use the Linq extension GroupBy.  This article also provides an in depth explanation of that least used and somewhat misunderstood extension. Examples are give with related and non related keys to help one understand the flexibility of the extension.
Note that this code can be used in any .Net version from 3.5 and greater.

Finding Identical Strings using GroupBy

Searching for duplicates in lists can be done in different ways but with the introduction of GroupBy extension in Linq to Object queries one has a powerful tool to find those duplicates. GroupBy-s premise is to group items by a key and since keys in dictionaries are required to be unique, using this method to find duplicate items makes sense.
So let us define our problem in terms of a list of strings and somewhere within that list are duplicates which we want reported. For the sake of simplicity I won’t deal with case sensitivities to keep the example tight. The solution is as below with a line by line explanation of what is going on.
List<string> theList = new List<string>() { "Alpha", "Alpha", "Beta", "Gamma", "Delta" };

theList.GroupBy(txt => txt)
        .Where(grouping => grouping.Count() > 1)
        .ToList()
        .ForEach(groupItem => Console.WriteLine("{0} duplicated {1} times with these values {2}",
                                                 groupItem.Key, 
                                                 groupItem.Count(),
                                                 string.Join(" ", groupItem.ToArray())));
// Writes this out to the console:
//
// Alpha duplicated 2 times with these values Alpha Alpha

Line By Line Explanation

Line 1: Our generic list is defined with duplicate strings “Alpha” while Beta Gamma and Delta are only found once.
Line 3:
Using the extension method GroupBy. This extension is based off of an enumerable item (IEnumerable<TSource>) which is of course our list. The primary argument is and a Lambda function (Func<TSource, TKey>) where we will simply define our TSource as the input (our string of the list) and its lambda operation as the key for our grouping.
The key in our case for this scenario is our string which we want to find the duplicate in the list. If we were dealing with a complex object then the key might be a property or field off of the object to use as the key in other scenarios but it is not. So our key will be the actual item found within our list. Since GroupBy’s result behaves like a dictionary, each key must be unique and that is the crux of how we can use GroupBy to divine all identical strings.
Line 3: Before moving on we must understand what GroupBy will return. By definition it returns IEnumerable<IGrouping<TKey, TSource>>. This can be broken down as such:

  • IEnumerable simply means that it will return a list or multiple of items which will be of IGrouping<> type.
  • IGrouping is a tuple type object where it contains the key of the grouped item and its corresponding value.  The nuance of this item is that when it is accessed directly it simply returns the TSource item (the non key part, just its value).
If one is familiar with the Dictionary class then one has worked with the KeyValuePair and this is the same except for the direct access of the value as mentioned above is not found in KeyValuePair.
Line 4: With GroupBy returning individual lists of key value pairs of IGrouping objects we need to weed out the single item keys and return only ones of two of more and the Where does this job for us. By specifying a lambda to weed out the lists which only have 1 found key, that gives us the duplicates sought.
Line 5:
Change from IEnumerable returned from Where extension and get an actual List object. This is done for two reasons.
The first is that the ForEach is an extension method specific to a list and not a raw IEnumerable.
Secondly and possibly more importantly, the GroupBy extension is a differed execution operation meaning that the data is not generated until it is actually needed. By going to ToList we are executing the operation and getting the data back immediately. This can come into play if the original data may change. If the data can change its best to get the data upfront from such differed execution methods.
Line 6: The goal is to display all the duplicates found and demonstrate how an IGrouping object is used. In our example we only have one IGrouping result list but if the data were changed we could have multiple. The following will display the information about our current IGrouping list returned.
Line 7: By accessing the named Key property of a IGrouping object we get an individual unique key result which defines the list of grouping data found. Note just because we have grouped our data by a key which is the same as the data, doesn’t mean in another use of Groupby that the data will be the same. In our example the key is “Alpha” which we send to {0} of the string.Format.
Line 8: The count property shows us how many values are found in the grouping. Our example returns two.
Line 9: We will enumerate the values of this current grouping and list out the data values. In this case there are two values both being “Alpha”.

GroupBy Usage with Only Two Defined Keys Regex Example

Now that one understands the GroupBy, one must not think that multiple unique keys are the be all end all to its usage. Sometimes we may want group things into found and not found groupings. The following example takes our greek letter list above and finds all the  words ending in “ta”.
Here is how it is done:
List<string> theList = new List<string>() { "Alpha", "Alpha", "Beta", "Gamma", "Delta" };

theList.GroupBy( txt => Regex.IsMatch( txt, "ta$" ))
       .ToList()
       .ForEach(groupItem => Console.WriteLine("{0} found {1} times with these values: {2}",
                                                 groupItem.Key,
                                                 groupItem.Count(),
                                                 string.Join(" ", groupItem.ToArray())));
// Output
// False found 3 times with these values: Alpha Alpha Gamma
// True found 2 times with these values: Beta Delta
Using our old friend Regex we are going to check to see if the current string ends in ta. If it does it will be in the key grouping of True and if not it will be found in the False grouping by the result of IsMatch. The result shows how we have manipulated the groupings to divine that Beta and Delta are the only two in our list which match the criteria. Hence demonstrating how we can further use the GroupBy method.

GroupBy Usage with one Key or a Non Related Key

I have actually had a need to where I grouped all items in to one key and performed an aggregate method on the result. The tip here is to show that one doesn’t have to group items by related keys. In the following example we through everything into group 1. We could have called the group anything frankly and sometimes it is needed.
This final example shows how the GroupBy can be flexible.
List<string> theList = new List<string>() { "Alpha", "Alpha", "Beta", "Gamma", "Delta" };

theList.GroupBy(txt => 1 )
        .ToList()
        .ForEach(groupItem => Console.WriteLine("The Key ({0}) found a total of {1} times with a total letter count of {2} characters",
                                                 groupItem.Key,
                                                 groupItem.Count(),
                                                 groupItem.Sum(it => it.Count())));

// Output:
// The Key (1) found a total of 5 times with a total letter count of 24 characters
Share

Tags: , ,

Silverlight: Xaml Blend Namespace Error Not Resolved

XAML Namespace http://schemas.microsoft.com/expression/blend/2008 is not resolved.

This error can occur when certain Xaml elements added by blend have not been properly ignored during non design/debug situations and Blend or Visual Studio reports such error.

To resolve the error one must add the mc:Ignorable attribute to the namespace declarations to inform the Xaml compiler to ignore a specific specified namespace at appropriate times. T0 fix the above error where the blend namspace is qualified by d one needs to ingore D as shown on the highlighted line:

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"

How Does This Happen?

I ran into this recently when Blend 4 added Xaml to allow me to populate (bind generated data) to a datagrid during design time (only in blend mind you) to work with the design data. Of course the blend namespace was there, but it never added the ignorable. It actually failed due from this line because its bringing in the blend namespace here, though I was never informed of the exact line.

<Grid x:Name="LayoutRoot"
      HorizontalAlignment="Stretch"
      d:DataContext="{d:DesignData /SampleData/HomeViewModelSampleData.xaml}">

One can see the ‘d’ namespace qualifier which relates to the blend namespace declaration as shown above. Since its job is to bring in sample data, that obviously should not be expressed during runtime and was not ignored.

Once one understands this situation the resolution seems trivial but it is one which has to be learned.

Share

Tags: , ,