Archive for category C#

Silverlight (How To): Manipulation of Dynamic Selection Rubber Band in C#

Large group of women exercising in the parkOne of the basic tenets of WYSIWYG is to be able to create a rubber band region using the mouse to give the user the ability to create a selectable region. This article demonstrates how to do that in any version of Silverlight and the user is given the tools to create such a bounding rectangle in any circumstances via the usage of some basic building blocks in Silverlight.

The below picture (not the one on the left) shows our goal, the dynamic creation of a bounding rubber band (a rectangle control for this demonstration) in a canvas. The below canvas is drawn in black (visually grey due to the opacity set) while the bounding rectangle shows itself in red.

RubberBanding

The user starts the process with an initial click which designates a start location of an upper left point for our bounding box with a mouse click.  Once the click happens the mouse cursor changes to a hand (if moving to the lower right) as a visible indicator that the process has started. While user continues to move to the lower right the band grows and while the mouse button has yet to be let go or released. For the demo a bounded number is shown is which relates the actual dynamic change in the X (horizontal) position. That is done for this article only and the above picture shows the rectangle with an X size of 123 pixels and can still be grown as shown by the hand icon.

Initial Xaml

In the page’s xaml we add a grid and a canvas as such this:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition Height="33*" />
        <RowDefinition Height="267*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="32*" />
        <ColumnDefinition Width="568*" />
    </Grid.ColumnDefinitions>
    <Canvas x:Name="cMain"
            MouseLeftButtonDown="cMain_MouseLeftButtonDown"
            MouseLeftButtonUp="cMain_MouseLeftButtonUp"
            MouseMove="cMain_MouseMove"
            Grid.Row="1"
            Grid.Column="1">
        <TextBlock Width="100"
                    Height="30"
                    Text="{Binding XValue, ElementName=userControl}"
                    />
        <Rectangle Fill="Black"
                    Width="550"
                    Height="200"
                    Opacity=".25"/>
    </Canvas>
</Grid>

The things to note are that the canvas is in a grid which is offset from the initial by 30 pixels in both axis. We then place a rectangle on the canvas which is our area which will be our strike zone where we will intercept the messages mouse events. We have a strike zone because individual controls in a canvas, such as texblocks have whitespace between them and the canvas will not get the mouse clicks and we want to be able to capture the process at all locations on the canvas; hence we fill up the canvas with our strike zone as to be ensured that the events are consumed properly by the code. 

When the user clicks within the strike zone the process starts as signified by a cursor change to the hand, as the user moves within the zone the rubber banding increases and when the mouse button is let up the process ends and the cursor is returned to its previous state.

Initial Properties

Here are the three variables we will use during this process:

private int _xValue;

public int XValue
{
    get { return _xValue; }
    set
    {
        _xValue = value;
        OnPropertyChanged( "XValue" );
    }
}

private Point OriginatingPostionOnCanvas { get; set; }

private Rectangle RubberBandBox { get; set; }

Since the XValue property is reflected on the screen in a text box it reports all changes by using  INotifyPropertyChanged which our class handles in a standard way for notify property (not shown). Followed by that is our initial click location named OriginatingPostionOnCanvas which will dictate the upper left (or lower right) location of the rubber band rectangle which we will dynamically create. The last variable is the actual dynamic rectangle control named RubberBandBox which will be created and modified during the process.

Event Mouse Left Button Down

We will handle three events during this process. The first is the when the user clicks and begins to hold down the mouse button:

private void cMain_MouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
    OriginatingPostionOnCanvas = e.GetPosition( cMain );

    RubberBandBox = new Rectangle() { Width = 1, 
                                      Height = 1, 
                                      Fill = new SolidColorBrush( Colors.Red ), 
                                      Opacity = .1
                                    };

    RubberBandBox.SetValue( Canvas.LeftProperty, OriginatingPostionOnCanvas.X);
    RubberBandBox.SetValue( Canvas.TopProperty,  OriginatingPostionOnCanvas.Y );

    cMain.Children.Add( RubberBandBox );
}

Our goals here are simple:

  1. Get and store the location where the user clicked in relation to the canvas.
  2. Create  and store the rectangle in red and with an opacity which does allows the user to see what is being selected.
  3. Setting the initial location of the rectangle and adding it to the children of the canvas.

Event Mouse Move

The user is moving and we must adjust the rectangle as appropriate for the target direction. Note we also have to handle when the user moves to the upper left instead of the lower right…. So when that happens we will change the cursor to a Stylus (the dot) for visual indication that we are getting a reverse band situation.

private void cMain_MouseMove(object sender, MouseEventArgs e)
{
    if (RubberBandBox == null)
        return;

    Point pointMovedTo = e.GetPosition( cMain );

    double xDelta = pointMovedTo.X - OriginatingPostionOnCanvas.X;
    double yDelta = pointMovedTo.Y - OriginatingPostionOnCanvas.Y;

    LayoutRoot.Cursor = ((xDelta > 0) && (yDelta > 0)) ? Cursors.Hand : Cursors.Stylus;

    if (LayoutRoot.Cursor == Cursors.Hand)
    {
        RubberBandBox.Height = yDelta;
        RubberBandBox.Width  = xDelta;
    }
    else if (LayoutRoot.Cursor == Cursors.Stylus)
    {
        RubberBandBox.Height = Math.Abs( yDelta );
        RubberBandBox.Width = Math.Abs( xDelta );

        if (xDelta < 0)
            RubberBandBox.SetValue( Canvas.LeftProperty, pointMovedTo.X );

        if (yDelta < 0)
            RubberBandBox.SetValue( Canvas.TopProperty, pointMovedTo.Y );
    }

    XValue = (int) (e.GetPosition( cMain ).X - OriginatingPostionOnCanvas.X);
}
Explanation
Line 3 The mouse can move through the canvas during times we are not processing. We need to check that and only process when we have an actual rectangle on the canvas.
Line 6 Extract the current location in relation to the canvas.
Line 8-9 Get the change differences for x and y as named deltas.
Line 11 If the deltas retrieved are in the positive we have a drag to the lower right and that is designated by or specifying the cursor to a hand. If not, the deltas indicate that movement is upwards and to the left; regardless change the  cursor to the stylus.
Line 13 If we are in the hand state, we want to grow (or decrease) the rectangle in that direction towards the lower right.
Line 18 If we are in the stylus state, there is a negative growth either in the x or y axis. Handle the negatives while changing the height and width. Depending on which delta is negative, handle the new location position of the upper left hand position of our bounding rectangle which will follow the mouse.
Line 30 Inform the user of the current X axis location of the mouse whether positive or negative.

Event Mouse Left Button Up

This is our final event we have to handle. We do a safety check on whether we are actually in operations, and if we are then we simply return the cursor to its original state and remove the rectangle from the canvas’ children.

private void cMain_MouseLeftButtonUp( object sender, MouseButtonEventArgs e )
{
    if (RubberBandBox == null)
        return;

    // Return to the previous state; whatever it is, the OS handles it.
    LayoutRoot.Cursor = null; 

    cMain.Children.Remove( RubberBandBox );

    // Show that we are not processing by making this null.
    RubberBandBox = null; 
}
Share

Tags: , , ,

.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: , ,

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: , ,

C#: WPF and Silverlight DataGrid Linq Binding Example Using Predefined Column Header Names in Xaml

iStock_000015057287XSmallThis snippet is from my archives and reminds me how to setup column names for a WPF/Silverlight datagrid and bind them to the data by not using AutoGenerateColumn feature. (See below for the visual end result.)

Ω Check out the related post Xaml: Adding Visibility Behaviors Using Blend to A DataGrid for WPF or Silverlight

DataGrid Column Names Setup in Xaml

In this example we will have two columns where the data will be filename strings. We will specify the columns in the Xaml to use the DataGridTextColumn and not to dynamically generate columns on our Datagrid:

<DataGrid x:Name="dgOperation" AutoGenerateColumns="False">
    <DataGrid.Columns>
        <DataGridTextColumn Header="File Name Before" Binding="{Binding Path=Original}"/>
        <DataGridTextColumn Header="File Name After"  Binding="{Binding Path=New}"/>
    </DataGrid.Columns>
</DataGrid>

The result is that the header row will have two columns with the name “File Name Before” and “File Name After” will subsequently bind them to a data object with the property names of “Original” and “New”.

Actual Binding During the Loading of the Grid

We will read in a directory for the WPF example from the hard drive and fill the original file names to the first column and a generated name for the second column. Since we have specified in the Xaml that we are binding to “Original” and “New” properties the dynamic linq object created will have those properties.

dgOperation.ItemsSource = Directory.GetFiles( @"C:\" )
                                   .Select( ( nm, index ) => new
                                       {
                                          Original = System.IO.Path.GetFileName( nm ),
                                          New = string.Format( "{0}_{1}{2}", System.IO.Path.GetFileNameWithoutExtension( nm ),
                                                                             index,
                                                                             System.IO.Path.GetExtension( nm ) )
                                        } );

The result is as below:

DataGridBind

Note: Out of the box editing the rows will throw an exception. To fix that make each of the rows read only.

Share

Tags: , , ,

C#: Access a Resource .resx File and a Corresponding Enum To Create a Dictionary

iStock_000013436514XSmall(Update 5/16/2011: Fixed mispelling)
I ran across a situation where the code I was working on had an enum with values and I needed to display a user friendly text which was related to the enum but not the enum’s actual text value.

The standard way of mapping values across cultures is to create a localized resource file(s) (.resx) and to put in string key and a string value, where the value will be shown. The code can then do an if check to map between the two; but that gets laborious real quick. It would be better to have a dictionary where the enum is the key and the value is the value of the resources file.

The following snippet of code takes in an enum and its corresponding resource resx data and creates that dictionary. See the section Steps to Test for an example of its usage.

/// <summary>
/// Take an enum and a created corresponding resx resource file and join the two together 
/// into a dictionary. The dictionaries key is the actual enum and the value is the user readable text
/// found in the value of the resource file.
/// </summary>
/// <typeparam name="T">The Enum type which contains the target enums</typeparam>
/// <param name="rm">The .resx resource's manager which contains the mapped text</param>
/// <returns>A dictionary whose key is the enum and the result is the mapped text in the resource file.</returns>
public static Dictionary<T, string> LoadResourceEnumMappings<T>( ResourceManager rm )  
{
    T[] eValues = (T[])System.Enum.GetValues( typeof( T ) ); // Gets the actual values of the enum (T) type

    // Puts those into a local dictionary/hash for use in later.
    var dictEnum = eValues.ToDictionary( it => it.ToString(), it => it ); 

    // Work through the key value pairs (KVP) of the resource set and marry them
    // to a new dictionary where the key is the enum and the value output is the user string
    // as found in the resource's value of its kvp.
    return rm.GetResourceSet( Thread.CurrentThread.CurrentCulture, true, false )
             .OfType<DictionaryEntry>()
             .ToDictionary( kvp => dictEnum[kvp.Key.ToString()], kvp => kvp.Value.ToString() );

}
NOTES
  • One can have more resource keys than enums and the above will work. But if there are more enums than resource keys, the above code will throw a KeyNotFound exception.
Enumerate the Embedded Resource

The above code uses the ability to enumerate or iterate the resource file by calling GetResourceSet. That calls returns a Dictionary entry which has the key value pair of the resource file and could be used with a foreach.

Steps To Test
  1. Create console application
  2. Create enum named MappedValues with these enums : Alpha, Beta, Gamma.
    public enum MappedValues
    {
        Alpha,
        Beta,
        Gamma
    }
  3. Create Resource File named UserText.Resx with these values:Resx 

Test as such with this code by calling EnumMapper.Usage():

public static class EnumMapper
{
    /// <summary>
    /// This is just for show and not meant for production.
    /// </summary>
    public static void Usage()
    {
        try
        {
            Console.WriteLine( "Load resource and show: " + UserText.Alpha );

            Dictionary<MappedValues, string> mapped = LoadResourceEnumMappings<MappedValues>( UserText.ResourceManager );

            Console.WriteLine( mapped[MappedValues.Alpha] );

            Console.WriteLine( mapped[MappedValues.Beta] );

            Console.WriteLine( mapped[MappedValues.Gamma] );
        }
        catch ( KeyNotFoundException )
        {
            Console.WriteLine("The Resource File has a key which is not found in the enum.");
        }

/* outputs (Note "first value" was shown to initialize the ResourceManager otherwise it would be null from GetResourceSet)
Load resource and show: First Value
First Value
Second Item
Third Wave
*/
    }

    /// <summary>
    /// Take an enum and a created corresponding resx resource file and join the two together 
    /// into a dictionary. The dictionaries key is the actual enum and the value is the user readable text
    /// found in the value of the resource file.
    /// </summary>
    /// <typeparam name="T">The Enum type which contains the target enums</typeparam>
    /// <param name="rm">The .resx resource's manager which contains the mapped text</param>
    /// <returns>A dictionary whose key is the enum and the result is the mapped text in the resource file.</returns>
    public static Dictionary<T, string> LoadResourceEnumMappings<T>( ResourceManager rm )  
    {
        T[] eValues = (T[])System.Enum.GetValues( typeof( T ) ); // Gets the actual values of the enum (T) type

        // Puts those into a local dictionary/hash for use in later.
        var dictEnum = eValues.ToDictionary( it => it.ToString(), it => it ); 

        // Work through the key value pairs (KVP) of the resource set and marry them
        // to a new dictionary where the key is the enum and the value output is the user string
        // as found in the resource's value of its kvp.
        return rm.GetResourceSet( Thread.CurrentThread.CurrentCulture, true, false )
                    .OfType<DictionaryEntry>()
                    .ToDictionary( kvp => dictEnum[kvp.Key.ToString()], kvp => kvp.Value.ToString() );

    }

}
Share

Tags: , , , ,

C#: String Extension SplitOn to Split Text into Specific Sizes

Update 7/11/2016 Updated Code To use Linq

This code string extension which will take a specific max line size and fit only words into those lines.

For example if one split on this sentence: “The Fall River” would make three strings of “The “, “Fall “ and “River”.

I have placed this into a string extension which could be called such as

List<string> items = "The Fall River".SplitOn( 5 );

Here is the extension method

// using System.Text.RegularExpressions;
public static class StringExtensions
{

    /// <summary>Use this function like string.Split but instead of a character to split on, 
    /// use a maximum line width size. This is similar to a Word Wrap where no words will be split.</summary>
    /// Note if the a word is longer than the maxcharactes it will be trimmed from the start.
    /// <param name="initial">The string to parse.</param>
    /// <param name="MaxCharacters">The maximum size.</param>
    /// <remarks>This function will remove some white space at the end of a line, but allow for a blank line.</remarks>
    /// 
    /// <returns>An array of strings.</returns>
    public static List<string> SplitOn( this string initial, int MaxCharacters )
    {

        List<string> lines = new List<string>();

        if ( string.IsNullOrEmpty( initial ) == false )
        {
            string targetGroup = "Line";
            string pattern = string.Format( @"(?<{0}>.{{1,{1}}})(?:\W|$)", targetGroup, MaxCharacters );

            lines = Regex.Matches(initial, pattern, RegexOptions.Multiline | RegexOptions.CultureInvariant )
                         .OfType<Match>()
                         .Select(mt => mt.Groups[targetGroup].Value)
                         .ToList();          
        }
        return lines;
    }
}

Here is an example with output of its usage:

string text = "The rain in spain falls mainly on the plain of Jabberwocky falls.";

List<string> lines = text.SplitOn( 20 );

foreach ( string line in lines )
    Console.WriteLine( line );

/*
The rain in spain
falls mainly on the
plain of Jabberwocky
falls.
 */

foreach ( string line in text.SplitOn( 11 ) )
    Console.WriteLine( line );

/*
The rain in
spain falls
mainly on
the plain
of
Jabberwocky
falls.
 */
Share

Tags: