Category Archives: C Sharp

The WPF CheckBox

Checkboxes in WPF are very straight forward controls, very similar to their WinForms predecessors. Adding them is a simple matter of using the <CheckBox> tag. Likely you’ll need to give each a name, so you can reference it in code.

There are also two properties that may be of use to you. First is IsChecked, this is set to true or false and as you might expect sets whether the check is in the box or not. The second is IsEnabled, and determines whether users may use the control. You can combine these in any combination, as you can see in the example below.  

    <StackPanel>

      <CheckBox Name=cbxOne IsChecked=False>Check Box One</CheckBox>

      <CheckBox Name=cbxTwo IsChecked=True>Check Box Two</CheckBox>

      <CheckBox Name=cbxThree IsChecked=False IsEnabled=False>Check Box Three</CheckBox>

      <CheckBox Name=cbxFour IsChecked=True IsEnabled=False>Check Box Four</CheckBox>

      <Button Name=btnShowMe Click=btnShowMe_Click>Show Me</Button>

    </StackPanel>

This little bit of code produces this attractive dialog:

wpf044

Note I’ve added a button, the purpose of the button is to show you a dialog that determines whether a box is checked.  

    void btnShowMe_Click(object sender, RoutedEventArgs e)

    {

      StringBuilder sb = new StringBuilder();

 

      if (cbxOne.IsChecked==true)

        sb.AppendLine(“Box One is Checked”);

      else

        sb.AppendLine(“Box One is Unchecked”);

 

      if ((bool)cbxTwo.IsChecked)

        sb.AppendLine(“Box Two is Checked”);

      else

        sb.AppendLine(“Box Two is Unchecked”);

 

      MessageBox.Show(sb.ToString(), “CheckBox”);

 

    }

Here you can see all that’s needed is to check (no pun intended) the IsChecked property. You may wonder why I had to use the bool case in the cbxTwo example. It turns out the IsChecked is actually of type bool? and not bool. A bool? is a bool that can hold a null value in addition to true/false.

In the cbxOne area, the .Net Framework can handle converting the bool? to a bool before it does the equal. In the second example, .Net needs that conversion to be made explicit.

Go ahead and run the app, check the boxes and click the Show Me to see the messages. I didn’t bother to repeat the same code for boxes three and four, since they are disabled, but they’d work the same way.

The WPF CheckBox is something you should check out! (OK, that time the pun was intended! 😉

The WPF ComboBox

The other major listing control to cover is the ComboBox. It turns out that they are almost identical to ListBoxes. This simple code will add a combo box to your container (I’m using a StackPanel) and put two items into it.

      <ComboBox>

        <ComboBoxItem>Item 1</ComboBoxItem>

        <ComboBoxItem>Item 2</ComboBoxItem>

      </ComboBox>

Running will produce the predictable window with a drop down combo box and two items. If you want the user to be able to edit or enter his own text, you will need to set the IsEditable property to true and IsReadOnly to false in the <ComboBox> header.

Also like the ListBox, the ComboBox can contain complex items.

      <ComboBox>

        <ComboBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Anna</TextBlock>

            <Image Source=D:\Presentations\100Anna.jpg Height=100 />

          </StackPanel>

        </ComboBoxItem>

        <ComboBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Raven</TextBlock>

            <Image Source=D:\Presentations\100Rave.jpg Height=100 />

          </StackPanel>

        </ComboBoxItem>

        <ComboBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Ammie</TextBlock>

            <Image Source=D:\Presentations\100Ammie.jpg Height=100 />

          </StackPanel>

        </ComboBoxItem>

        <ComboBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Kids</TextBlock>

            <Image Source=D:\Presentations\100Kids.jpg Height=100 />

          </StackPanel>

        </ComboBoxItem>

 

      </ComboBox>

wpf040

Note from the image above, if the contents of the drop down are too big it wil drop below the bottom of your current Window. Additionally, if you use automatic sizing the combo box will adjust itself rather oddly depending on the contents. For that reason, you may wish to set a default width rather than letting the combo box do it for you.

So how do we get data back out of the ComboBox? Well, if all we have is text, we can do just like we did with the ListBox, convert the selected item to a combo box item and get it’s Content.ToString property. But what if it’s like the above example, a mixture of text and images? Well we have to dig just a little, but it’s not that difficult if you understand the tree WPF creates.

  <StackPanel>

    <ComboBox Name=myComboBox  >

      Item Data Omitted for Brevity

    </ComboBox>

    <Button Name=myButton Content=OK Click=myButton_Click />

  </StackPanel>

Note I made two changes. First I added a name to the ComboBox, that way I can address it in code. Next I added a simple button control, we’ll use it to show what is currently selected. Just for the fun of it, I used the Content tag instead of placing it between the <Button></Button> tags, you may run across that form of syntax at some point and should be aware of it.

Now we need to add a little code to the myButton_Click event.

    public void myButton_Click(object sender, RoutedEventArgs e)

    {

      ComboBoxItem cbi = myComboBox.SelectedItem as ComboBoxItem;

      if (cbi != null)

      {

        StackPanel sp = cbi.Content as StackPanel;

        TextBlock block = sp.Children[0] as TextBlock;

        MessageBox.Show(“You picked “ + block.Text);

      }

      else

      {

        MessageBox.Show(“You haven’t picked anything yet”);

      }

    }

First, I got the current ComboBox item, and stored it in the cbi variable. I then check to see if it’s null, which it will be if the user hasn’t selected anything. If it is, we can show them the traditional “hey dummy” message, as I did in the else clause.

If you recall, the contents of the ComboBoxItem are a StackPanel control, so next I get a reference to it in the sp variable.

Next, I suppose I could iterate of the Children of the StackPanel, but since I know that the TextBlock I want is the first child, I’ll simply reference it directly as element zero and return it to the block variable.

Finally we can get to the actual text for the row the user picked. We can simply reference the TextBlock’s text property in the message box. When the app is run, you should see these results:

wpf041

The same techniques I use here would also be applicable to the ListBox we’ve seen previously, simply replace ComboBoxItem with ListBoxItem.

The WPF ComboBox can be quite useful for providing a compact way for users to select complex items.

WPF ListBox

Another old and faithful control that has made the transition to WPF is the ListBox. It’s pretty simple to create a ListBox, and load some values into it.

      <ListBox>

        <ListBoxItem>Item 1</ListBoxItem>

        <ListBoxItem>Item 2</ListBoxItem>

        <ListBoxItem>Item 3</ListBoxItem>

      </ListBox>

Of course the ListBox isn’t much good if you can’t get the value out of it. To do that we’ll have to add a few things.

      <Button Name=ShowSelected Click=ShowSelected_Click>Show Selected</Button>

      <ListBox Name=lbxDemo>

        <ListBoxItem>Item 1</ListBoxItem>

        <ListBoxItem>Item 2</ListBoxItem>

        <ListBoxItem>Item 3</ListBoxItem>

      </ListBox>

 

Here I added a button that would show which item was selected, then I had to give the ListBox a name we could refer to. Following techniques I’ve previously laid out (https://arcanecode.wordpress.com/2007/09/07/adding-wpf-controls-progrrammatically/) I added a click event for the button.

Now, you might think you could just enter something like

      MessageBox.Show(“You Selected “ + lbxDemo.SelectedValue);

And get a message back. But instead what you get is:

 

wpf033

This is because the SelectedValue is actually a ListBoxItem, and not a value. Instead you need to get the content of the ListBoxItem thusly:  

      ListBoxItem lbi = (lbxDemo.SelectedItem as ListBoxItem);

      MessageBox.Show(“You REALLY selected “ + lbi.Content.ToString());

Now you’ll see:

wpf034

Note that you’re not just restricted to ListBoxItems. I could, for example use checkboxes:

      <ListBox Name=lbxCheckMe>

        <CheckBox>Item 1</CheckBox>

        <CheckBox>Item 2</CheckBox>

        <CheckBox>Item 3</CheckBox>

        <CheckBox>Item 4</CheckBox>

      </ListBox>

wpf035

Like other controls, you can stack other controls inside the contents of a ListBoxItem. Let’s get a little fancy, and create a list box with both text and images.

      <ListBox Name=lbxCool>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Anna</TextBlock>

            <Image Source=D:\Presentations\100Anna.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Raven</TextBlock>

            <Image Source=D:\Presentations\100Rave.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Ammie</TextBlock>

            <Image Source=D:\Presentations\100Ammie.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

        <ListBoxItem>

          <StackPanel Orientation=Horizontal>

            <TextBlock Width=100>Kids</TextBlock>

            <Image Source=D:\Presentations\100Kids.jpg Height=100 />

          </StackPanel>

        </ListBoxItem>

      </ListBox>

    </StackPanel>

(Note you can use any images, I used a few of my kids and wife.) The result is this:

wpf036

This covers some basics on using a ListBox, enough to get you started with your own lists.

Adding WPF Controls Progrrammatically

On August 29th I wrote a posting about the StackPanel (https://arcanecode.wordpress.com/2007/08/29/stacking-the-deck-with-the-wpf-stackpanel/). A commentor asked “how do you add controls programmatically?” Good question, and it turns out to be quite easy.

Let’s create a sample app, and add a new window. I named mine AddControls. Here’s the XAML:

<Window x:Class=WPFSample001.AddControls

    xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation

    xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml

    Title=AddControls Height=114 Width=212

    >

  <StackPanel Name=splMain>

    <Button Name=btnAddMore Click=btnAddMore_Click>Add Another</Button>

  </StackPanel>

</Window>

And here’s what it looks like:

wpf029

A few things I’d like to point out. I’ve given a name to the StackPanel, so it can be manipulated in our C# code. I also added a handler for the Click event for the button, btnAddMore_Click. I also named the button, although it really wasn’t necessary for this sample.

OK, make sure to build the app so intellisense will work, then let’s jump to the C# code behind. (You may get an error about the click handler for the button not being found, that’s fine just ignore it.)

First, we’ll create an event handler for the button, passing in the sender and routed event args, like I discussed yesterday (https://arcanecode.wordpress.com/2007/09/05/the-wpf-button/) . Then, all we have to do is create a button control and add it to the children collection of the StackPanel, like so: 

    public void btnAddMore_Click(object sender, RoutedEventArgs e)

    {

      System.Windows.Controls.Button newBtn = new Button();

      newBtn.Content = “A New Button”;

      splMain.Children.Add(newBtn);

    } 

 

Note in this example I used the fully qualified System.Windows.Controls, I did that just to be explicit where the Button came from. After a new button is created, I set it’s Content property, which in this case will be the text on the button.

In the final line, I add it to the children collection of the StackPanel. When you run it, and press the “Add Another” Button, you will see:

wpf030

Now we have a new problem. We’ve added a button to the StackPanel, but clicking on it does no good as we haven’t tied it to an event handler. Turns out that’s pretty easy too.

    public void btnAddMore_Click(object sender, RoutedEventArgs e)

    {

      System.Windows.Controls.Button newBtn = new Button();

      newBtn.Content = “A New Button”;

      newBtn.Click += new RoutedEventHandler(newBtn_Click);

      splMain.Children.Add(newBtn);

    }

 

What I did was use a delegate. I added a new RoutedEventHandler and tied it to the click event. The code for the event is in a method named newBtn_Click:

    private void newBtn_Click(object sender, RoutedEventArgs e)

    {

      MessageBox.Show(“New Button Clicked!”, “I got pressed.”);

    }

 

The signature for the event handler has to match the signature for a Click event, since that’s what we’re routing to. Here, all I do is display a message box just so you can see something got done. Run it again and press the Add Another button, and the “A New Button” should appear. Press the new button and you should see a message box.

wpf031

Finally, I want to be clear you can use this technique to add any sort of control. Here I’ve added a Label as well as a button:

    public void btnAddMore_Click(object sender, RoutedEventArgs e)

    {

      System.Windows.Controls.Button newBtn = new Button();

      newBtn.Content = “A New Button”;

      newBtn.Click += new RoutedEventHandler(newBtn_Click);

      splMain.Children.Add(newBtn);

 

      System.Windows.Controls.Label newLbl = new Label();

      newLbl.Content = “Hi Mom!”;

      splMain.Children.Add(newLbl);

    }

wpf032

I could have created the entire form in C# (or VB.Net) code, adding the StackPanel directly to the “this” object. However, that gets a bit laborious, and I wouldn’t recommend it as a general practice.

Starting a WPF Project

Head colds are nasty things. Yeah, I know folks like Scott Hanselman and Jeff Atwood say we shouldn’t talk much about ourselves, but I offer this as explanation for dropping off the face of the earth last week. A nasty head cold, followed by busy work week and my houses air conditioning dying in the middle of an Alabama triple digit heat wave… well something had to give.

But hey, odds are you’re not hear to offer your chicken soup recipe, but find out about WPF. So let’s kick this week off by starting a WPF project. Assuming you followed my instructions in my last post ( https://arcanecode.wordpress.com/2007/08/20/installing-the-wpf-bits/ ), you now have all the bits installed. Open Visual Studio 2005, and create a new project.

In your “New Project” window, navigate down to the “NET Framework 3.0” branch. In the templates area you see some new ones. One, WCF Service Library, is for creating Windows Communication Services projects and is outside the scope of this discussion.

The other three are WPF oriented projects. Windows Application (WPF) is for creating general windows applications using WPF. This is what you’ll probably use the most, and what we’ll pick for today’s demo. I named mine WPFSample001, as you can see above.

Before you click OK, let me just mention the other two. Custom Control Library (WPF) is analogus to it’s “old fashioned” WinForms counterpart. It lets you create a custom control comprised of WPF pieces for use in WPF Windows projects.

XAML Browser Application (WPF) is used to create a WPF App that will run inside a browser. Note this isn’t Silverlight. This is more like a Click Once deployment that opens the app inside the browser. MSDN (Sep 2007) had a good example of one you can see for yourself at http://ttpdownload.bl.uk/browserapp.xbap .

OK, that covers the various WPF project types. For today, we’ve decided on a standard WPF Windows Application, so click OK as you see in the screen above.

Let’s take a quick tour of what you see. Over on the left is the Toolbox. Under Common Controls, we see some with names look familiar. Button, CheckBox, Lable, etc. These are the WPF versions of the old Windows Forms controls. There are some new controls too, such as the DockPanel, the StackPanel, and a Grid which is unlike any Grid you’ve used in the past. We’ll get into these as time goes by.

Over on the right, in the Solution Explorer you see the Files that make our WPF project. App.xaml (and it’s corresponding App.xaml.cs) is the starting point for our Windows WPF app. Here you can respond to events like application starting and stopping, or you can blissfully ignore it.

The Window1.xaml is your main focus now, since it’s where you can do all your work. If you look at the center pane, you’ll notice it’s a bit different from traditional Windows Forms or even ASP.Net designer, in that it gives you the nice split screen. Changes in one are reflected in the other.

If you don’t like the split, you can modify it by either moving the mouse in the middle area and adjusting where the spit occurs, or manipulate it using the controls on the right side of the tab area:

The left most button flips the split from the default horizontal to a vertical one, nice if you have a really wide screen monitor. The middle button returns the split to the default horizontal orientation. The right most button removes the split all together, putting two tabs at the bottom (one for designer, one for xaml), not unlike the experience you get today when designing ASP.Net html pages.

Before I close out today, I want to mention that the designer tool under 2005 is not fully baked. You will see a lot of “whoops” screens appear. In addition, control placement is more like the ASP.Net experience than WinForms. As such, most folks I’ve seen so far prefer to type the XAML code directly in.

To start with I’ll be doing just that, typing in the XAML which will help me learn the behind the scenes syntax. Later I’ll shift to using the Expression Blend tool as the main XAML designer.

This is a good start, tomorrow we’ll pick up with creating a simple XAML app.

Arcane Searching

I think we’d all agree the internet is one of the greatest productivity tools around, allowing us to find vast stores of information. I’m sure you’ve also heard it’s the greatest time waster, with lots of distracting sites or useless pages that get in the way of the results we want.

I find it really valuable to have a good search tool, one that focuses on the content I need, and limits the scope of the search to relevant areas. Of course we’ve all heard of Google, the 500 pound gorilla of search engines. While the do a pretty decent job, when your search phrase returns half a million hits it can be difficult to narrow down.

Recently I’ve found the Microsoft engine, Windows Live ( http://www.live.com/ ), has gotten a lot better, especially when looking for .Net related developer content.

My favorite so far though, is Search.Net ( http://searchdotnet.com/ ), a site put together by coding legend Dan Appleman. Dan ( http://www.desaware.com/ ) created a Google powered site, but maintains the list of sites it searches so you know that you are only combing sites devoted to programming and not Happy Harry’s House of Wild Women.

Another site I just learned about this week is Koders ( http://www.koders.com/ ). It’s a site devoted to searching through source code. It also has some helps that will let you zoom in on what you want. You can pick the language, or specify your search word needs to be in the class name, method name, or interface name. This kind of search is valuable when you are looking for an example, or trying to avoid reinventing the wheel.

A similar site is Krugle ( http://www.krugle.com/ ). It has similar paradigm to Koders, allowing you to search through code.

The final code search tool I’ll mention is Google’s new Code Search engine ( http://www.google.com/codesearch?hl=en ). It allows you to search using regular expression syntax, which is a nice feature (I just wish regular expressions weren’t such a pain in the underwear to use).

I have to give a quick thanks, most of these I learned about through either my listening of Dot Net Rocks ( http://www.dotnetrocks.com/ ) and HanselMinutes ( http://www.hanselminutes.com/ ) or through Scott Hanselman’s new forum site, which I blogged about yesterday.

Those are the list of place I go when I need to find something, how about you?

Arcane Add-Ins: KNOCKS Solutions VS 2005 Add-In

It’s been a while since I talked about Visual Studio add-ins, so when I ran across KNOCKS Solutions “Knocks VS2005 Add-In”, I knew I’d found the perfect subject. Available at http://www.knocks-solutions.com/VS2005Addins.aspx?sm=idVS20052 , this rather full featured add-in offers many utilities.

First is a personal clipboard, that allows you to store and retrieve up to 9 different items. And they’re persistent, they will stay between VS sessions.

Next is a code snippets manager. This seems a bit redundant in light of VS 2005’s snippets, but I can see it being very useful during a presentation.

In addition to the code snippets is a Notes module. I’ve often wished for the ability to store quick notes to use in a presentation, so this is a handy module.

Up next is the one tool of theirs I have a beef with, the “Re-arrange code” tool. I like the idea of being able to re-arrange my code. Often I’m working on some public method, and realize I need a private helper method and, being in a hurry and lazy, will drop it right under the public method. Later I’ll move it around, which was why I was excited to see this tool.

Sadly, it has a really bad side affect, it strips out any regions you’ve put into your code, and it strips out any comments that might lie between methods (I often put a comment header right above my method, instead of in the method.) When Knocks rearranges your code all of that goes into the bit bucket, making the tool useless in all but (perhaps) the very earliest stages of coding. I would have thought it possible to add regions to the tool as well, and allow code rearranging within a region, between regions, or even to move regions around. Perhaps this will be addressed in the next version (he said, ever full of eternal hope).

There is a nifty zip tool that will zip your entire project, handy for quick backups. Also is a tool that embraces the concept of a favorites for projects. Another tool is one I wonder why no one did sooner, a keyword search on Google (or other configurable search engine, like MS Live). This is one I’ll be using often.

Also included is a simple “Data Object” generator. You bring it up and enter a few property names and types and Knocks will create the basic class for you. While I have seen more full featured code generators, I appreciate the basic simplicity of this one, not to mention the price (which I’ll get to shortly).

knocks01The final two tools I’ll mention are my favorites. First is a Design Explorer. This adds an explorer window (I put mine with the Solution Explorer area) to your display. In it are all the controls for your current form. Clicking on the control not only makes it the active control in the designer, but displays the properties in the lower half of the Design Explorer window.

 

 

 

 

 

 

 

 

 

knocks02The other tool is the Code Explorer. It displays a tree of your current code module. Double clicking on the code element will take you to it in the code window.

I’ve seen other add-ins with code windows, this one seems equal in functionality with many others similarly priced.

 

 

 

 

Oh, did I forget to mention the price? It’s free. Yes, FREE. Knocks has packed a lot of functionality into this add-in, and the fact it’s free makes it well worth the time to download and learn.

Arcane Talks

On Thursday July 12th I’ll be speaking at the Birmingham Software Developers Association (BSDA). You can get directions from the club’s website, http://www.bsda.info/ .

I’ll be speaking on the subject of SQL Server Compact Edition. It’s been a while since I blogged about this, so I thought I’d provide a few links for quick reference.

As promised, here is a link to the Power Point presentation (in PDF format) I used during the presentation:

 SSCE presentation for BSDA user group

My very first post was back in January 2007:

http://shrinkster.com/nsk

My next series of posts began on April 10th, and described how to create databases using the various tools available to you.

http://shrinkster.com/qtl

The complete C# and VB.Net code samples were posted April 13th, 2007:

http://shrinkster.com/qtm

And finally, the series of posts I mentioned on system Views started with this post on April 16th, 2007:

http://shrinkster.com/qtn

If you want to see all of my SSCE posts, simply click the SQL Server Compact Edition tag over in the categories area, or use this link:

 https://arcanecode.wordpress.com/tag/sql-server-compact-edition/

Please note each of these links is a starting point, be sure to read the blog for the next few days after each link in order to get the full story.

And now a question, I’m working up material for a new presentation. Debating between SQL Server 2005 Full Text Searching and SQL Server Integration Services. Any opinions?

Eventually I’ll do both, but would like to do the first one based on feedback. Even if you can’t attend please post a comment and let me know where your interests lie.

Collections in C#: NameValueCollection

In doing some reading I ran across a handy collection called the NameValueCollection. This collection, which resides in the System.Collections.Specialized namespace, allows you to use either a string or an integer index for the key. Further, it allows you to store more than one string value in a key.

Let’s start the code example by creating a simple Console application. I added using references to System.Collections and System.Collections.Specialized namespaces at the top. As a final bit of housekeeping, make sure to add a Console.ReadLine() as the last line of our code, so the console will wait on us to hit the enter key after we read the results. (If you don’t, the program will run so fast you won’t be able to appreciate your fine work.)

Now I’m going to load some data into a new collection called myCollection. For the data, I’ll use a website owner and the website or sites they own.

      System.Collections.Specialized.NameValueCollection myCollection

        = new System.Collections.Specialized.NameValueCollection();

 

      myCollection.Add(“Arcane”, http://arcanecode.com&#8221;);

      myCollection.Add(“PWOP”, http://dotnetrocks.com&#8221;);

      myCollection.Add(“PWOP”, http://dnrtv.com&#8221;);

      myCollection.Add(“PWOP”, http://www.hanselminutes.com&#8221;);

      myCollection.Add(“TWIT”, http://www.twit.tv&#8221;);

      myCollection.Add(“TWIT”, http://www.twit.tv/SN&#8221;);

Next, I’d like to get some data back out. I mentioned you could cycle through the collection using an integer index, so let’s see how that’s done:

      Console.WriteLine(“Key / Value Pairs by Integer Index”);

      for (int i = 0; i < myCollection.Count; i++)

      {

        Console.WriteLine(i.ToString() + ” “

          + myCollection.GetKey(i) + “: “

          + myCollection.Get(i));

      }

 

[Picture of Key/Value pairs by Integer Index]

 

In the above output you can see how I use the GetKey and Get methods to retrieve the key name and value for that key using the loop’s index. Note that when multiple values are associated with a single key, they are returned as a list of comma separated values.

You can also use foreach logic to cycle through the collection. Here I am using the AllKeys property of our collection to get the list of keys. I can then print the key, and also use the key as the indexer into my collection as you can see below.

      Console.WriteLine();

      Console.WriteLine(“Keys / Value Pairs via AllKeys Collection”);

      foreach (string myKey in myCollection.AllKeys)

      {

        Console.WriteLine(myKey + “: “ + myCollection[myKey]);

      }

 

[Picture of Key/Value pairs via AllKeys Collection]

 

Now I, what? Yes, you in the back row, what was your question? Ah, you say lists of comma separated values are OK, but you want to be able to access individual values? Fortunately some nested looping and the GetValues method will satisfy you demanding types.

 

      Console.WriteLine();

      Console.WriteLine(“Keys / Individual Values”);

      foreach (string myKey in myCollection.AllKeys)

      {

        foreach (string myValue in myCollection.GetValues(myKey))

        {

          Console.WriteLine(myKey + “: “ + myValue);

        }

      }

 

[Picture of Keys/Individual Values]

 

This also works great if your data has commas within it. Let’s add two lines back at the top of the program to the collection.

      myCollection.Add(“CommaTest”, “Here is a , in a string”);

      myCollection.Add(“CommaTest”, “Here is another , in a string”);

 
Now run the application again, and lets look at the results.
 
[Picture of Comma Test]

As you can see in the last area “Keys / Individual Values” the GetValues method correctly determined that the commas I had embedded were part of the data and not a delimiter between values.

Whenever you need a good string collection that has the ability to tie multiple values to a single key, the NameValueCollection would be a good class to take a look at.

 

Arcane Tools: Cropper

Well, the uber cool Scott Hanselman has done it again, found another gem. OK, he’s been using it for a while, but in watching his GrokTalk ( see my post on Tuesday ) I learned about Cropper.

Cropper is a screen capture tool. As you can see below, it puts an translucent window on your screen. You can move and resize this window with the mouse, or the keyboard.

[Pic of Cropper in action]

The arrow keys will move the cropper window in 1 pixel increments for fine tuning, or for quick moves combine the arrows with the CTRL key to make 10 pixel jumps. You can also resize, use ALT plus the arrows for 1 pixel resizes, or CTRL+ALT+arrow for 10 pixel resizing jumps.

You have the option to save in a variety of formats, including BMP, PNG, and JPG, and can even select a level of JPG compression. You can also save to the clipboard if you so desire.

To capture an image, simply double click on the translucent cropper window, or press ENTER. When you do, a file is written to your Documents folder in a subfolder called Cropper Captures (although this is user configurable). I like this, as it lets me quickly grab one screen shot after another without having to put a lot of thought into it.

The coolest thing about Cropper though, is it’s entirely written in C#, and open source so you can see all the code. It comes courtesy of Brian Scott, you can see his blog and download Cropper for yourself at http://blogs.geekdojo.net/brian/articles/Cropper.aspx .

The only negative I’ve found is the name. Apparently cropping is also a popular term in the scrapbooking world, so when I started talking about cropper my wife ( http://southerntinkerbelle.com ) got all excited and tought I was getting into scrapbooking! I hated to disappoint her, but on the bright side the sofa really wasn’t all that uncomfortable.

Thanks for coming!

I just wanted to thank everyone who took the effort to come to the presentation I did tonight on SQL Server Compact Edition at the Birmingham Dot Net Users Group ( http://www.bugdotnet.com ). It was a small crowd but very engaged, all in all a very enjoyable evening for everyone.

As promised, here is a link to the Power Point presentation (in PDF format) I used during the presentation:

SSCE presentation for BUG.Net group

The complete C# and VB.Net code samples were posted April 13th, 2007:

https://arcanecode.wordpress.com/2007/04/13/sql-server-compact-edition-with-c-and-vbnet/

And finally, the series of posts I mentioned on system Views started with this post on April 16th, 2007:

https://arcanecode.wordpress.com/2007/04/16/system-views-in-sql-server-compact-edition-tables/

If you want to see all of my SSCE posts, simply click the SQL Server Compact Edition tag over in the categories area, or use this link:

https://arcanecode.wordpress.com/tag/sql-server-compact-edition/
Thanks again to  everyone, I had a great time and hope came away with a better understanding of SQL Server Compact Edition.

Arcane GUI’s: Enabled versus Visible Properties

I was having a discussion with a coworker today about the user interface for his application. There is an Admin menu that the site IT folks will need to setup the application for the first time on a computer.

He was mentioning he was going to make the Admin menu disabled for non IT folks, and instead I suggested he make it invisible. Why? He asked. Good question.

Human nature is the best answer. Your average user is going to be content with what they have, but there will always be those who want more. They are curious about what they are missing out on, or are not satisfied unless they think they are getting the “full” software, even if it’s functions they don’t need.

In large corporations, these folks tend to be, er well rather insistant, and if they have a supervisor who likes to take the easy way out, he may wind up telling IT to grant the user access he shouldn’t have.

Instead, I have a firm design principle: Ignorance is bliss. In this case, if the Admin menu were hidden, the problematic users would never know it even exists, and live in happy igornace, causing problems elsewhere.

So here’s the rule: If there is functionality a user will never have access to, such as an Admin menu, then it should be hidden via the Visible property.

On the other hand, if there is functionality that is enabled or disabled based on the state of the app, use the Enabled property. A good example might be the Copy function on the Edit menu. If no text is selected, then Copy should be disabled as there’s nothing to copy. It servers as a visual cue the user has the application in a state that the Copy function makes no sense. Once text is selected, Copy should be Enabled.

Another example might be a Save function, if the required fields are not completed, disable the Save as a cue to the user he still has work to do.

And there you go, Arcane’s GUI Rule for Enabled versus Visible Properties.

Windows Services in C#: Pulling in the Event Log for your Windows Service (part 8)

Technically this falls in line closer with the EventLog series I did in January. (For more info see my series on event logging, it started on January 16 of this year and ran to the 19th, http://shrinkster.com/p6d). However, in most cases the Event Log is tied in closely with Windows Services since it’s through the event log that services do most of their communication with the outside world. As such it can be important to read in your events back into your control app.

To read the log we’ll use two different methods, just to show multiple techniques. To start, let’s add a text box to the TLManager, under the buttons. I named mine txtEventLog. Next, in the component area of the toolbox find the EventLog component and drop it on the form. Like the timer, it goes in the tray area under the form. I named mine TimerEventLog.

In the properties for the TimeEventLog, there’s a few properties we must set. First, set the Log property to “ArcaneTimeLogger” and the Source to “ArcaneTimeLoggerService”, so it will know to read our log.

Next set EnableRaisingEvents to true. This will allow the EventLog component to raise an event whenever something gets written to our log. Since we set this to true, we must indicate what method is responsible for the event. Click on the Event button (the lightening bolt) in the properties window to switch to events view, then double click the EventWritten to generate a default named event. It will generate TimeEventLog_EntryWritten.

Now switch to code view, and add this code to the event:

    private void TimeEventLog_EntryWritten(object sender, System.Diagnostics.EntryWrittenEventArgs e)

    {

      txtEventLog.Text = e.Entry.Message

        + System.Environment.NewLine

        + txtEventLog.Text;

    }

This will take the latest event log entry, and add it to the text box. Note I put it first, then add back what was already in the text box. This way the most recent event will always be at the top.

That’s it for this part, now everytime something is written to the event log, the EventLog component will catch the event and let us know about it.

Nice, but sometimes you also want to know what’s already there in the log. Instead of using a component let’s see how to do this with code. First, add a “using System.Diagnostics” reference to the header of your class (form).

Now, I think it would look nice when the TLManager loads to already have the text box populated with the past events. The System.Diagnostics library contains an EventLog class we can use to create an object for our particular event log. Once that’s done, we can cycle through the Entries collection to read what’s there. Here’s some code I added to the TLManger_Load event to do just that.

      StringBuilder sb = new StringBuilder();

      EventLog atl = new EventLog(“ArcaneTimeLogger”);

      for (int i = atl.Entries.Count – 1; i > -1; i–)

      {

        sb.AppendLine(atl.Entries[i].Message);

      }

      txtEventLog.Text = sb.ToString();

I start by creating a string builder object to hold all of the events. Next, and the key is the EventLog atl… line. I pass in the name of our log so the atl object will know what log it belongs to.

Next you will see a for loop that cycles through the entries. Note I’m deliberately starting with the last entry, the most recent one, and counting down to the oldest one. This will ensure the most recent event appears first in the text box.

Finally, I copy the data we’ve built into the string builder into the text box. And that’s it, two ways to monitor event logs and pull their data into your application.

Windows Services in C#: Sending Commands to your Windows Service (part 7)

Yesterday we looked at starting and stopping your windows service from another application. It would also be helpful to be able to send other commands beyond the basic set of Start/Stop/Pause etc.

On the good side, there is an API through which it is possible to send a command to your windows service, fairly easily as a matter of fact. The down side is it’s a one way communication, through the built in mechanism it’s not possible to return any data. Even more limiting is the only data you are allowed to pass in is an integer, and it’s value must be between 128 and 255.

Even with those limitations, if all you need to do is execute a few simple commands the built in API can be more than enough to meet your needs.

To illustrate, we’ll expand the windows service we’ve been using as an example. We’ll add the ability to send a command that will force the event log to be updated immediately, rather than waiting on the timer to fire off its event.

First, we’ll add two items to the service. The first is a public enum. Strictly speaking we don’t have to use an enum, but it makes for more readability.

    // Must be int between 128 and 255

    public enum commands

    {

      LogIt = 255

    }

Next we’ll add a new method to the windows service called OnCustomCommand. This is an override to the base classes method. As you can see it first calls the base method, then checks the value of the integer that was passed in, in this case against our enum. If it finds a match, it calls the WriteToLog method immediately. (The WriteToLog was discussed yesterday, so I won’t reiterate here).

    protected override void OnCustomCommand(int command)

    {

      base.OnCustomCommand(command);

      if (command == (int)commands.LogIt)

      {

        WriteToLog(“Arcane LogIt:”);       

      }

    }

OK, that’s all that’s needed for the service. Let’s switch to our program, and add another button called LogIt.

[Pic of TLManager]

Now we’ll add a little code to the click event for the log it button.

    private void btnLogIt_Click(object sender, EventArgs e)

    {

      ServiceController sc = new ServiceController(“ArcaneTimeLogging”);

      sc.ExecuteCommand(255);

    }

Like in our other examples we create a reference to our service by creating a new ServiceController object and passing in the name of our service. Once we have an sc object we call the ExecuteCommand method. This allows us to send messages to a windows service.

Numbers 0-127 are reserved for windows, and are handled in the base class. 128 to 255 are there for your own use. In the example above I used 255 just to show that you could pass an integer value directly without using an enum.

One last small item, we don’t want the LogIt button to be enabled if our service isn’t running. We’ll add a little logic to the SetDisplay, Start and Stop methods to include setting the buttons enabled status properly. Here’s the updated routines.

    private void SetDisplay(ServiceController sc)

    {

      sc.Refresh();

      if (sc.Status == ServiceControllerStatus.Stopped)

      {

        btnStop.Enabled = false;

        btnStart.Enabled = true;

        btnLogIt.Enabled = false;

        lblStatus.Text = “Stopped”;

      }

      if (sc.Status == ServiceControllerStatus.Running)

      {

        btnStart.Enabled = false;

        btnStop.Enabled = true;

        btnLogIt.Enabled = true;

        lblStatus.Text = “Running”;

      }

    }

 

    private void btnStart_Click(object sender, EventArgs e)

    {

      ServiceController sc = new ServiceController(“ArcaneTimeLogging”);

      sc.Start();

      btnStart.Enabled = false;

      btnStop.Enabled = true;

      lblStatus.Text = “Running”;

      sc.Refresh();

    }

 

    private void btnStop_Click(object sender, EventArgs e)

    {

      ServiceController sc = new ServiceController(“ArcaneTimeLogging”);

      sc.Stop();

      btnStop.Enabled = false;

      btnStart.Enabled = true;

      lblStatus.Text = “Stopped”;

      sc.Refresh();

    }

And that’s all there is to it. Compile and reinstall your service, then launch your TLManager program. With the service started, click the LogIt button a few times then go into MMC and take a look at your event log. You should see a new message appear each time you click the LogIt button.