IgorShare Thoughts and Ideas

Consulting and Training

Archive for the ‘Software’ Category

Upcoming Northeast developer events and talks

Posted by Igor Moochnick on 07/07/2008

Hartford, CT CodeCamp – August 16

I’m planning to bring an agile-development-related presentation. I think it’s a time to start razing a bar for the community’s developer skills level.

Let me know if there are any other requests for the presentations.

I’ve never been to Hatford, CT – what are the favorite places and to-do things there?

For more Northeast developer events see Chris Bowen’s post.

Posted in Alt.Net, Community, Software, Thoughts, Tutorials | Leave a Comment »

CodeCamp (Waltham, MA) was a great success

Posted by Igor Moochnick on 04/06/2008

The last 2 days we had CodeCamp #9 in Waltham. It was a great success – 555 registered  participants (I swear it was 5 more than allowed 550). A lot of great presentations and presenters. I want personally thank the organizers and the participants.

I’ve given 4 presentations – 2 intro sessions and 2 in-depth session. Audience was great, engaging, friendly and asked a lot of good questions.

You’re welcome to download the presentations and the source code. Feel free to ask questions over the e-mail.

  1. PowerShell – extending your projects with PowerShell “To Infinity … and Beyond” (samples source code)
  2. Workflows are … not only for Business (samples source code)

I hope to see all of you next CodeCamp or during User Group meetings.

Posted in Pash, PowerShell, Presentations, Software, Thoughts, Tutorials, Workflows | 1 Comment »

Pash – cross platform PowerShell is out in the wild! Announcement.

Posted by Igor Moochnick on 04/06/2008

Pash – http://pash.sourceforge.net/

PowerShell open source reimplementation for “others” (Mac, Linux, Solaris, etc…) and Windows (including Windows Mobile and Windows CE)

About the name

Pash = PoSH (PowerShell) + bash (one of the Unix shells)

Goals

The main goal is to provide a rich shell environment for other operating systems as well as to provide a hostable scripting engine for rich applications. The user experience should be seamless for people who are used to Windows version of PowerShell. The scrips, cmdlets and providers should runs AS-IS (if they are not using Windows-specific functionality). The rich applications that host PowerShell should run on any other operating system AS-IS. Secondary goal: the scripts should run across the machines and different OS’s seamlesly (but following all the security guidelines).

Environment

The current implementation of Pash is written using pure .Net 2.0. It compiles on VS 2008 as well as on Mono. So all the developers can choose the environment that fits their needs and preferences. The produced assemblies can be executed “right out of the box” on Windows, Linux, Mac (or others) without any additional recompilation. Note: for Windows Mobile and Windows CE the produced code should be recompiled against the .NET Compact Framework.

Progress

You’re welcome to get the source code and contribute to the Pash public effort @ http://sourceforge.net/projects/pash.

~50% of public PowerShell classes defined.

~40% of framework functionality operational.

Stay tuned for more detailed info. Trying to figure out how to produce the similar class diff that Mono project is using.

Screenshots

Windows (duh !..)

Pash on Mono + SuSE Linux

Pash on Compact .NET Framework

and (drum roll …) Pash on Mac


Posted in Pash, PowerShell, Software | 64 Comments »

Custom Event Log trace listener/writer

Posted by Igor Moochnick on 02/05/2008

Ever wanted to route a bunch of your trace events to an event log for IT administrator to see? In .NET you can do this without even changing a single line of your code. I’m sure a lot of you already seen the default event trace listener, but, if you used it you’ve noticed, it doesn’t allow you much control of how and where these events are landed. In my project I needed such control to tell what events, to what event log and with what event source they’ll find their way in. So, to do this, I needed a new EventLogListenerEx (see the code below). This new EventLogListenrEx can be put easily into your configuration by the standard means:

   1: <sharedListeners>
   2:   <add name="eventLogListener" type="Yosemite.Utilities.EventLogListenerEx,Yosemite.Utilities" 
   3:        initializeData="Log=Application;Source=MyServer">
   4:     <filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning" />
   5:   </add>
   6: </sharedListeners>

 

Note the “initializeData” attribute – it allows you to control to what Log and with what Source the events will be routed. This new event listener will create a new event source on demand if it’ll not find one, but, of cause, it should have enough privileges to do so. BTW: you can always create a required event source when needed from a stand-alone command line tool where you can have as much privileges as needed.

Enjoy!

    public class EventLogListenerEx : TraceListener
    {
        private string _EventLogName = "Application";
        private string _EventLogSource = "Application";
        private string _EventLogType = "Information";
        private EventLog _eventLog;
        private EventLogEntryType _logType;

        public EventLogListenerEx(string logType)
            : base()
        {
            System.Diagnostics.Trace.WriteLine("Event log processing");

            try
            {
                string[] parts = logType.Split(';');

                foreach (string part in parts)
                {
                    string[] settings = part.Split('=');

                    if (settings[0].ToLower() == "log")
                    {
                        _EventLogName = settings[1];
                    }
                    else if (settings[0].ToLower() == "source")
                    {
                        _EventLogSource = settings[1];
                    }
                    else if (settings[0].ToLower() == "type")
                    {
                        _EventLogType = settings[1];
                    }
                }

                _eventLog = new EventLog(_EventLogName);
                bool bRet = false;
                try
                {
                    bRet = EventLog.SourceExists(_EventLogSource);
                }
                catch (SecurityException)
                {
                    System.Diagnostics.Trace.WriteLine("Not enough credentials to create an event source - switching to Application.");
                    bRet = true;
                    _EventLogSource = "Application";
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine("Unexpected exception while checking for an event source: " + ex.ToString());
                    bRet = true;
                    _EventLogSource = "Application";
                }
                if (! bRet)
                {
                    try
                    {
                        EventLog.CreateEventSource(_EventLogSource, _EventLogName);
                    }
                    catch (SecurityException)
                    {
                        System.Diagnostics.Trace.WriteLine("Not enough credentials to create an event source - switching to Application.");
                        _EventLogSource = "Application";
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Trace.WriteLine("Unexpected exception while creating an event source: " + ex.ToString());
                        _EventLogSource = "Application";
                    }
                }

                _eventLog.Source = _EventLogSource;
                _logType = (EventLogEntryType)Enum.Parse(typeof(EventLogEntryType), _EventLogType);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Trace.WriteLine(ex.ToString());

                throw;
            }
        }

        public override void Write(string message)
        {
            string str = message.Trim();

            // Just in case - we'll log the event if it's not a Trace header
            if (str[str.Length - 1] != ':')
            {
                WriteLine(str);
            }
        }

        public override void WriteLine(string message)
        {
            _eventLog.WriteEntry(message, _logType);
        }
    }

Posted in C#, Software, Tutorials | Leave a Comment »

Did you know: using ToLower on a Unicode text can cause a security problem?

Posted by Igor Moochnick on 01/26/2008

Recently watched the latest DnrTV show #97 (love them!) with Kathleen Dollard (check her blog Leaning Into Windows). Great show! Kathleen went through a lot of things that are rarely used in the day-to-day projects but, if overlooked, can cause a serious problem and put the whole project/product at risk. Here are 2 that are really worth remembering:

1. In a product that works with Unicode strings (Localized) and do a lot of string comparisons, it’s better to use ToUpper than ToLower. ToUpper will not work correctly for a couple of languages, but ToLower, not only fail for more languages, but, also, can expose a bunch of security problems within Unicode implementation.

2. Do not write ANY code that changes variables in a partial method call. If a partial method implementation will be removed – such code will be removed as well and will cause an unpredictable result. To understand this check out the following code snippet:

   1: partial void PrintNum(int n);
   2:  
   3: public int AddWithIncrement(int a, int b)
   4: {
   5:    PrintNum(a++);
   6:    return a+b;
   7: }

 

Let’s say that a=1 and b=2. If the PrintNum method will have a declaration, then the AddWithIncrement function will return 4. On the other hand, if the declaration of PrintNum will be removed, the compiler will remove (ignore) the whole line #5 (PrintNum(a++)), hence the a++ will not be executed and AddWithIncrement function will return 3.

So, be careful, you have been warned!

Posted in C#, Software, Thoughts, Tutorials, Visual Studio | Leave a Comment »

.NET Source Code is available for public

Posted by Igor Moochnick on 01/17/2008

You can find all the details of how to configure your Visual Studio in a detailed Shawn Burke’s article. It looks like the WPF source can be in there too according to Bart hints on his B#.NET blog.

Posted in Software, Tutorials, Visual Studio | 1 Comment »

Free Silverlight training at Lynda.com

Posted by Igor Moochnick on 01/12/2008

lynda.comThanks to Mike Taulty’s post, I can add yet another great training video collection to my library – Silverlight Essential Training on Lynda.com.

I’ve already pointed your attention to Lynda.com’s free WPF training videos in one of my previous posts, so keep an eye on evergrowing great training resource.

Posted in Silverlight, Software, Tutorials | Leave a Comment »

CodeDom extensions and dynamic LINQ (string/script to LINQ emitting)

Posted by Igor Moochnick on 01/11/2008

Ah… Don’t you like these method extensions?!!!

Recently I’ve developed a certain taste for method extensions. They allow to create shorter code, but you should always keep in your head the dangers of such freedom – code can become complicated and unnatural. On the other hand, new set of extensions, it’s like to learn a new language, new classes, new techniques. So, currently, I have a mixed feeling – great thing, but not for free (some overhead attached).

In my previous post (Intellisense-like method selection pop-up window) I’ve shown how to create a LINQ editor (or any editor of your choice). You can ask – what’s the point of such script? What can we do with it?

.NET answer – the sky is your limit. The .NET framework allows you dynamically convert any string (correctly formatted) into a code and immediately execute it. You can do this in-memory, in-file, from-file, to-file, from-string, to-string, and any other combination of your choice.

Here are a couple of example of what you can do with a correctly formatted string:

  1. Generate a full code file
  2. Generate an assembly in-memory
  3. Create an assembly in file for future use
  4. etc …

As well you have a wide choice of code providers:

  1. C#
  2. VB.NET
  3. C++
  4. JavaScript
  5. and any other code provider that is installed on your machine and inherits from System.CodeDom.Compiler.CodeDomProvider class.

To simplify the use of CodeDom (it requires a wide knowledge of how the build process works), I’ve created a very basic library that extends CodeDom functionality and provides a nice and slick way of generating code-on-the-fly. Here are a couple of small examples, before we’ll dive into how it’s done (find them in the attached test project):

A) The following snippet prints Hello World! to the console:

   1: var c = new CodeDom();
   2: c.AddNamespace("Samples").Imports("System")
   3:     .AddClass(
   4:       c.Class("TestClass")
   5:         .AddMethod(c.Method("Print", "Console.WriteLine(\"Hello World\");")));
   6: 
   7: var methodPrint = c.Compile().GetType("Samples.TestClass").GetMethod("Print");
   8: methodPrint.Invoke();

B) And here is the example of how to call a function with parametes (it’ll add 2 numbers):

   1: var c = new CodeDom();
   2: c.AddNamespace("Samples").Imports("System")
   3:     .AddClass(
   4:       c.Class("TestClass")
   5:         .AddMethod(c.Method("int", "AddNumbers", "int a, int b", "return a + b;")));
   6: 
   7: var methodAddNumbers = c.Compile().GetType("Samples.TestClass").GetMethod("AddNumbers");
   8: int retVal = Converter.To<int>(methodAddNumbers.Invoke(2, 3), 0);
   9: // retVal = 5

C) and here is the BEST – dynamic LINQ (compiled and executed in memory):

   1: var c = new CodeDom();
   2: c.AddReference(@"System.Core.dll")
   3:     .AddNamespace("Samples")
   4:     .Imports("System.Collections.Generic")
   5:     .Imports("System.Linq")
   6:     .AddClass(
   7:       c.Class("TestClass")
   8:         .AddMethod(c.Method("IEnumerable<string>", "FilterCollection", "IEnumerable<string> items",
   9:              "return from item in items where item.StartsWith(\"a\") select item; ")));
  10: 
  11: var method = c.Compile().GetType("Samples.TestClass").GetMethod("FilterCollection");
  12: 
  13: var items = new List<string>() { "apple", "banana", "ananas", "mango" };
  14: IEnumerable<string> retVal = (IEnumerable<string>)method.Invoke(items);
  15: // retVal contains: "apple", "ananas"

Obviously you can start mix and match these extensions and create more namespaces, classes with more methods, etc … I don’t want to get too much into the details (see attached test project for more samples), but rather I want to tell how it works.

NOTE: Yes, I know about the Dynamic LINQ library and I’ve read ScottGu’s blog article, but, so far, I’ve seen only that you can create filters with this technique. It is using tokenized parser behind the scenes and reflects expression tree based on the results. This has somewhat limited functionality and can’t emit expression tree solely based on a string LINQ query. May be in the future it’ll be expanded, but, at this moment, my solution is the only way to convert LINQ string to an executable code.

Extension methods are the key. CodeDom class just provides a set of factories to create the CodeDom classes like CompileUnit, CodeTypeDeclaration, CodeSnippetTypeMember, etc… It collects all the namespaces, referenced assemblies, constructed code and, at the end, it allows you to decide what is a final product of your actions. The beauty of the code ensured by the extension methods.

I will not go too much into details of how to create extension methods themselves (a lot of information can be found on the net), but rather talk about the most important one: Method.Invoke.

   1: public static object Invoke(this MethodInfo methodInfo, params object[] parameters)
   2: {
   3:     return methodInfo.Invoke(null, parameters);
   4: }

This extension method makes the constructs like “method.Invoke()” and “method.Invoke(2, 3)” possible. It hides the complexity of the reflection from the users and allows him to use the newly constructed method as if it’s a real method of the application.

At the end I want to mention, yet another, beauty of .NET – dynamic type converter. Such converter allows you to  take control over your untyped objects without second-guessing your type conversion assumptions and skipping all the error check logic. I’ve used such technique very extensively with untyped DataSets in all my middle tier applications (I’ll be posting about it soon). For example, Method.Invoke always returns an object. If you want to use the returned value as a strongly typed object – you have to cast it to the required type either by “()” or “as” constructs. Then you need to check for a “null” or an exception. In my case you can do something like this:

   1: int retVal = Converter.To<int>(methodAddNumbers.Invoke(2, 3), 0);

Note the last “0” in the converter’s call – this is a default value that will be returned in case the conversion has failed. This is how it works:

   1: /// <summary>
   2: /// Converts from "object" general type to a concrete type
   3: /// </summary>
   4: /// <remarks>
   5: /// The class is working with .Net 2.0 and above
   6: /// </remarks>
   7: public class Converter
   8: {
   9:     /// <summary>
  10:     /// Returns True if the type can get Null as a value (is a reference type and not a value one)
  11:     /// </summary>
  12:     public static bool IsNullable(Type t)
  13:     {
  14:         if (!t.IsGenericType) return false;
  15:         Type g = t.GetGenericTypeDefinition();
  16:         return (g.Equals(typeof(Nullable<>)));
  17:     }
  18: 
  19:     /// <summary>
  20:     /// Returns a real type of a first generic argument
  21:     /// </summary>
  22:     private static Type UnderlyingTypeOf(Type t)
  23:     {
  24:         return t.GetGenericArguments()[0];
  25:     }
  26: 
  27:     /// <summary>
  28:     /// Converter
  29:     /// </summary>
  30:     public static T To<T>(object value, T defaultValue)
  31:     {
  32:         if (value == DBNull.Value) return defaultValue;
  33:         Type t = typeof(T);
  34:         if (IsNullable(t))
  35:         {
  36:             if (value == null) return default(T);
  37:             t = UnderlyingTypeOf(t);
  38:         }
  39:         else
  40:         {
  41:             if ((value == null) && (t.IsValueType))
  42:             {
  43:                 return defaultValue;
  44:             }
  45:         }
  46: 
  47:         return (T)Convert.ChangeType(value, t);
  48:     }
  49: }

I’ll be talking about this converter in more detail in the future posts, so stay tuned …

The full source code with tests/examples you can find as usual on my web site: http://igor.moochnick.googlepages.com.

DISCLAMER: The provided libraries are a work in progress and do not contain 100% wrapped CodeDom. There are a lot of things that can be added to make the whole user experience easier. You are welcome to use them AS-IS and to extend them to any degree you with. You’re welcome to send me your updates and I’ll be more than happy to post them for everybody else to use.

Posted in C#, Software, Tutorials, Visual Studio | 9 Comments »

Intellisense-like method selection pop-up window

Posted by Igor Moochnick on 01/09/2008

Today the intellisense becomes a must in a whole range of different applications. Applications becomes smarter due to this enormous unharvested CPU power that is idling on your desktops and the applications find a way to use it.

The technique, I’m going to explain here, is a user-friendly way to hint or help user with their next actions while he works on his primary task. For example:

  1. user types a text, a spell checker (which is at your fingertips in WPF) finds the misspelled words and the application can suggest the user a choice
  2. user types a script and the application let’s the user to choice a next command from a list of possibilities
  3. etc…

 

We can go with the list, but, I hope, you got the idea. In my case, I’ll show you how help the user construct a LINQ query.

clip_image001

To make the explanation short and to the point, let’s scope the problem: the application will show a pop-up only when he types a predefined keyword and presses a “.” (dot). The popup will contain a list of possible methods that can be applied to the object.

Let’s create a class that will provide a list of item’s methods. Let’s say that item is of type SyndicationItem. So we’ll use reflection methods (if you don’t know what reflections it – you should look into it, it’s very useful in a whole range of applications) to find all the methods of the SyndicationItem type. You can use a “.GetType()” of an object or you can use a simple typeof(…) construct. The following code snippet does just this:

   1: public class ItemMethods
   2: {
   3:     public IEnumerable<string> Methods
   4:     {
   5:         get
   6:         {
   7:             Type type = typeof(SyndicationItem);
   8:  
   9:             var methods = (from method in 
  10:                                type.GetMethods(System.Reflection.BindingFlags.Public | 
  11:                                                System.Reflection.BindingFlags.Instance)
  12:                           select method.Name).ToList<string>();
  13:  
  14:             return methods;
  15:         }
  16:     }
  17: }

Now let’s go to blend and create our pop-up. Select a Popup control from the controls list and drop it anywhere on the form (better to put it on the object that it’ll be binded to or, at least, to on its parent layout element). You can put any single control on the pop-up, but, if you’d like to extend your functionality later, put some layout element. In my example you can see that I’ve put a Grid element. The ListBox that will be populated with our methods is positioned on the Grid. You have to set the following properties on the Popup:

  1. Placement=”Bottom” – this tells the system to position the pop-up at the bottom of the element it’ll be referring to. The same way as VS shows methods intellisense below and to the right of the “.” that you press.
  2. StaysOpen =”False” – this tells the WPF to close the Popup if it looses a focus
  3. IsOpen=”False” – hides the Popup on form initialization

To make the ListBox to display method names correctly you have to bind it to the ItemMethods class, we’ve defined previously. Don’t forget to compile your code – this will allow the Expression Blend to find it and help you with binding.

  1. Go to the advanced properties of the ItemsSource property (small rectangle to the right of the property value box) and click on Data Binding.
  2. Add the ItemMethods object from the list that will be presented to you after you press “+ CLR Object” button. This will add your new Data Source.
  3. On the Fields tree (on the right side) select the Methods collection.

If you did everything right – you’ll see a list of SyndicationItem methods in the Popup. Note that Expression Bled has added a new data source for you:

   1: <ObjectDataProvider x:Key="ItemMethodsDS" 
   2:     d:IsDataSource="True" 
   3:     ObjectType="{x:Type Castile:ItemMethods}"/>

and added a bind source to your ListBox: ItemsSource=”{Binding Path=Methods, Mode=OneWay, Source={StaticResource ItemMethodsDS}}

I’m preparing a big article about data binding (it’s a huge, powerful and extremely important part of WPF you should now), but in a nutshell this specific strings tell WPF to take the items from ItemMethodsDS data source from a proporty Methods.

At this point you’re free to customize your list box. For example I’ve decided to remove the scrollbars (HorizontalScrollBarVisibility=”Hidden” and  VerticalScrollBarVisibility=”Hidden”) and make the ListBox searchable (when you start type the letters it’ll jump to the item that starts with these letters).

   1: <Popup x:Name="popupLinqMethods" Height="Auto" Width="150" 
   2:        StaysOpen="False" Placement="Bottom" IsOpen="false" 
   3:        d:LayoutOverrides="Width, Margin" 
   4:        HorizontalAlignment="Left">
   5:     <Grid Width="Auto" Height="Auto">
   6:         <ListBox x:Name="lstMethodsSelection" 
   7:              ScrollViewer.HorizontalScrollBarVisibility="Hidden" 
   8:              ScrollViewer.VerticalScrollBarVisibility="Hidden" 
   9:              KeyDown="OnMethodsSelectionKeyDown" 
  10:              SelectedIndex="0" 
  11:              IsTextSearchEnabled="True" 
  12:              ItemsSource="{Binding Path=Methods, Mode=OneWay, Source={StaticResource ItemMethodsDS}}" 
  13:              ItemTemplate="{DynamicResource ListSyndicationObjectMethodsTemplate}"
  14:          />
  15:     </Grid>
  16: </Popup>

To make the Popup to disappear when you press Enter (after selecting a desirable item) or when you press Escape, we need to let the ListBox to handle these events. Hence you need an event handler (note the KeyDown=”OnMethodsSelectionKeyDown” property in the XAML above). To do this you have to put an event handler name in the KeyDown event on the event’s list of the ListBox. After you’ll press Enter, you’ll be taken back to the VS to edit your event handler. Here how it can look like:

   1: private void OnMethodsSelectionKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
   2: {
   3:     switch (e.Key)
   4:     {
   5:         case System.Windows.Input.Key.Enter:
   6:             // Hide the Popup
   7:             popupLinqMethods.IsOpen = false;
   8:  
   9:             ListBox lb = sender as ListBox;
  10:             if (lb == null)
  11:                 return;
  12:  
  13:             // Get the selected item value
  14:             string methodName = lb.SelectedItem.ToString();
  15:  
  16:             // Save the Caret position
  17:             int i = txtFilterText.CaretIndex;
  18:             
  19:             // Add text to the text
  20:             txtFilterText.Text = txtFilterText.Text.Insert(i, methodName);
  21:  
  22:             // Move the caret to the end of the added text
  23:             txtFilterText.CaretIndex = i + methodName.Length;
  24:  
  25:             // Move focus back to the text box. This will auto-hide the PopUp due to StaysOpen="false"
  26:             txtFilterText.Focus();
  27:             break;
  28:  
  29:         case System.Windows.Input.Key.Escape:
  30:             // Hide the Popup
  31:             popupLinqMethods.IsOpen = false;
  32:             break;
  33:     }
  34: }

All what we did so far was the control of the behavior and the content of the Popup, but we did nothing to trigger it appearance. Here your imagination is your limit. To make this sample work I’ve decided to show the Popup when the user will type the word “item.” in the script editor. As soon as he’ll press “.”  – the Popup will appear, allowing him to insert the selected method back to the script. The following KeyUp text box event handler’s code allows me to do just that. Note that the Key.OemPeriod value is used to identify the pressed “.” (dot). It wasn’t that obvious to me. Note, as well, the hardcoded “item.” hot-word. This is done to simplify the explanation. In your code it should be modified to reflect your needs.

   1: private void OnFilterTextKeyUp(object sender, System.Windows.Input.KeyEventArgs e)
   2: {
   3:     TextBox txtBox = sender as TextBox;
   4:     if ((txtBox == null) || (txtBox.CaretIndex == 0))
   5:         return;
   6:  
   7:     // Check for a predefined hot-key
   8:     if (e.Key != System.Windows.Input.Key.OemPeriod)
   9:         return;
  10:  
  11:     // Get the last word in the text (preceding the ".")
  12:     string txt = txtBox.Text;
  13:     int wordStart = txt.LastIndexOf(' ', txtBox.CaretIndex - 1);
  14:     if (wordStart == -1)
  15:         wordStart = 0;
  16:  
  17:     string lastWord = txt.Substring(wordStart, txtBox.CaretIndex - wordStart);
  18:  
  19:     // Check if the last word equal to the one we're waiting
  20:     if (lastWord.Trim().ToLower() != "item.")
  21:         return;
  22:  
  23:     ShowMethodsPopup(txtBox.GetRectFromCharacterIndex(txtBox.CaretIndex, true));
  24: }
  25:  
  26: private void ShowMethodsPopup(Rect placementRect)
  27: {
  28:     popupLinqMethods.PlacementTarget = txtFilterText;
  29:     popupLinqMethods.PlacementRectangle = placementRect;
  30:     popupLinqMethods.IsOpen = true;
  31:     lstMethodsSelection.SelectedIndex = 0;
  32:     lstMethodsSelection.Focus();
  33: }

It’s a little tricky to place the Popup exactly at the desired place – it has almost unlimited selection of different placement combinations (see MSDN help for the Placement property. In my case I needed, as I’ve mentioned above, to open it to the lower right from the pressed “.”. So my Popup has the Placement=”Bottom” – this will make it appear under the “.”.

How to find the “.” location – you’ll ask? That’s a great question!

It’s not that easy in Windows forms, but was super easy in WPF. The character location in a TextBox can be found by calling the GetrectFromCharacterIndex method. But this will give you the coordinates of the character inside the TextBox and the Popup will open in the incorrect place, because it’ll calculate it’s location relative to it’s parent Layout element. This is not what we need. To compensate the calculation we need to point the Popup PlacementTarget to our TextBox (see code above: PlacementTarget = txtFilterText).

Now we’re done! Start your script editor and start typing. You should see something very similar to the picture I’ve posted at the beginning of the post.

Posted in C#, Software, Tutorials, WPF | 5 Comments »

Creating custom shaped windows in WPF

Posted by Igor Moochnick on 01/08/2008

The unleashed power of WPF can do wonders, but be very carefull while creating custom shaped windows – keep the usability in mind. It should be clear to a user what each control represents and what the presented information means.

So, if you are planning to make you window cool, you have to drop the chains of the Windows themes. To do so you have to set the WindowStyle=”None”. This removed the window’s title bar, borders, control, maximize, minimize and close buttons – in simple words, EVERYTHING. This means you have to take control of the window into your hands. You have to give a user a way to close and move the window around. Don’t forget about the resize, if applicable.

To make your button close your window, you should set its Command property to ApplicationCommand.Close. If you’ll type “Close” in the Command property – Expression Blend will generate correct code for you. This is how this will look in Blend:

image

Setting the Command property will not do the all job. You need to bind the command to the actual action Window.Close() by using a CommandBinding class and assigning a new event handler. Here you can use Lambda notation to make the code simple.

   1: public partial class MainWindow
   2: {
   3:     public MainWindow()
   4:     {
   5:         this.InitializeComponent();
   6:  
   7:         // Bind the Close command to the close action
   8:         CommandBindings.Add(new CommandBinding(ApplicationCommands.Close,
   9:             new ExecutedRoutedEventHandler(( sender, args) => Close() )));
  10:  
  11:         // NOTE: for those who is not familiar with lambda expressions
  12:         // ( sender, args) => Close()   is literally equivalent to
  13:         // delegate(object sender, ExecutedRoutedEventArgs args) { this.Close(); }
  14:     }
  15:  
  16:     private void DragWindow(object sender, MouseButtonEventArgs e)
  17:     {
  18:         DragMove();
  19:     }
  20: }

To make my window draggable, I’ve associated the MouseLeftButtonDown event of the orange window corner to the DragWindow event.

You see, it’s easy. So go and experiment – unleash your imaginations.

Stay tuned for more WPF tips and tricks.

Posted in C#, Software, Tutorials, WPF | Leave a Comment »

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: