<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>midnight muse &#187; Projects</title>
	<atom:link href="http://midnightmuse.com.au/category/projects/feed/" rel="self" type="application/rss+xml" />
	<link>http://midnightmuse.com.au</link>
	<description>Richard Wright's musings about software and other things that take his fancy</description>
	<lastBuildDate>Thu, 06 May 2010 05:43:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Back to a WPF UI</title>
		<link>http://midnightmuse.com.au/2009/10/29/back-to-a-wpf-ui/</link>
		<comments>http://midnightmuse.com.au/2009/10/29/back-to-a-wpf-ui/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 14:11:13 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=141</guid>
		<description><![CDATA[I have found a better solution to the dual screen problem]]></description>
			<content:encoded><![CDATA[<p>In the previous post I wrote about the problem I had showing a WPF window on a second screen. And this is a major requirement of the application. After much searching I came to the conclusion that it could not be done easily. The only reasonable solution seemed to be building a winforms app and hosting a WPF control for the second screen. I tried that and it worked fine. The way to do it is pretty simple. I created a new project called WPFControls, it would get a better name in the real version – this is just to try it out – and created a WPF control which contained a Rich Textbox. It won&#8217;t stay that way; it will ultimately be a FlowDocumentReader or a FlowDocumentPageReader, but at this stage I don&#8217;t know which one. And in the previous code in WPF I had built a RichTextBox for editing songs and so, to test this line, I will just use the same code to load a song, hence the RTB.</p>
<p>The Rich TextBox loads the song from the database by reading in the flowdocument stored in the lyrics field for the song. All this is described in the previous articles.</p>
<p>On the windows form, which can  be shown on any screen, we place a control of type System.Windows.Forms.Integration.ElementHost. In my case this was given the name EditSongHost.<br />
When the EditSongForm is loaded it loads the WPF control and sets the Song property to the currently selected song.<br />
<code><br />
private void EditSongForm_Load(object sender, EventArgs e)<br />
{<br />
WpfControls.SongEditCtrl ctrl = new SongEditCtrl();<br />
ctrl.Song= song;<br />
EditSongHost.Child = ctrl;<br />
}<br />
</code></p>
<p>This worked just fine, but I now had a winforms application with some WPF controls, and this was a second best solution, as far as I was concerned. I really wanted a WPF application. I could have approximated that by building all the user controls in WPF and hosting all of them in windows forms, but that seemed to me to be madness. WPF is a relatively new technology, and maybe that was the only way possible at the moment. If so then, so be it.</p>
<p>But today I came across another solution on the <a href="http://forums.msdn.microsoft.com/en-US/wpf/thread/5d181304-8952-4663-8c3c-dc4d986aa8dd">Microsoft Forums</a>, in a reply given by Larry Olsen, WPF Program Manager. This is his solution</p>
<blockquote><p>1.<br />
Started a new WPF Application project in Visual Studio<br />
2.<br />
Added the needed references to System.Windows.Forms (needed for Screen) and System.Drawing (needed for Rectangle)<br />
3.<br />
Removed the StartupUri in the App.xaml file and overrode the OnStartup() method in code-behind. I did this because StartupUri points to just one Window, Window1.xaml, in the WPF Application template and OnStartup will let me control what happens when the application starts.<br />
4.<br />
Added Window2.xaml to the project so that I would have a second Window to display on a second monitor.<br />
5.<br />
Added code similar to the article you linked to the override of OnStartup  which was:</p>
<p>Code Block</p>
<p>protected override void OnStartup(StartupEventArgs e)<br />
{<br />
base.OnStartup(e);</p>
<p>Window1 w1 = new Window1();<br />
Window2 w2 = new Window2();</p>
<p>Screen s1 = Screen.AllScreens[0];<br />
Screen s2 = Screen.AllScreens[1];</p>
<p>Rectangle r1 = s1.WorkingArea;<br />
Rectangle r2 = s2.WorkingArea;</p>
<p>w1.Top = r1.Top;<br />
w1.Left = r1.Left;</p>
<p>w2.Top = r2.Top;<br />
w2.Left = r2.Left;</p>
<p>w1.Show();<br />
w2.Show();</p>
<p>w2.Owner = w1;</p>
<p>}</p></blockquote>
<p>I adapted that code so that the second window was displayed after clicking a button. It worked perfectly! I just need to make a few changes. First I needed to set the window style to none so that I had a full screen window with no title bar or maximise, minimise and close buttons. This is why it is important to set the window&#8217;s Owner property. If you don&#8217;t set that and close the main window the second screen is still active and the program is still running. In any event, the second screen needs to be entirely controlled by the primary screen.</p>
<p>When I ran the program the second screen duly opened, but it wasn&#8217;t maximised. So I set its WindowState to Maximized and then tried it. It was maximised but it was showing on the primary monitor, not the second monitor. Why was this happening? I have no idea. But after trying a few things I decided to call the Show method and then set the WindowState property to Maximized in code, after the Show() method. I don&#8217;t know why this makes a difference, but it does. Well, actually I can see why my solution works, but I don&#8217;t understand why setting the property before the Show() method makes a difference. I don&#8217;t know what is going on in the bowels of windows, and just to be sure I moved the WindowState property setting line of code to just before the Show() method, so that it was being set in code, not by the designer. I didn&#8217;t expect it to help, and it didn&#8217;t. No matter, it all seems to work fine.</p>
<p>Here is the code I used, hooked up to a temporary button<br />
<code><br />
private void btnShow_Click(object sender, RoutedEventArgs e)<br />
{<br />
DisplayWindow displayWindow = new DisplayWindow();<br />
Screen s2 = Screen.AllScreens[1];<br />
Rectangle rectangle = s2.WorkingArea;<br />
displayWindow.Top = rectangle.Top;<br />
displayWindow.Left = rectangle.Left;<br />
displayWindow.Show();<br />
displayWindow.WindowState = System.Windows.WindowState.Maximized;<br />
displayWindow.Owner = this;<br />
}<br />
</code></p>
<p>The only niggling doubt I have is that winforms and WPF use different units for screen and control measurement. Winforms uses pixels, and WPF doesn&#8217;t. Rather they have Device Independent Pixels which are equal to 1/96 of an inch. There are benefits to the way that WPF does its screen rendering, but even though it looks fine on my two monitor set up, I will have to test it on a projector which is likely to have a drifferent resolution to my monitor. I don&#8217;t think that WPF will have a problem with that, but the Screen properties, specifically the WorkingArea is a winforms property. I don&#8217;t expect a problem, but it will need to be checked.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2009/10/29/back-to-a-wpf-ui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Another Step Backward</title>
		<link>http://midnightmuse.com.au/2008/08/29/another-step-backward/</link>
		<comments>http://midnightmuse.com.au/2008/08/29/another-step-backward/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 00:37:55 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=137</guid>
		<description><![CDATA[WPF has a few idiosyncracies that can come back to bite you.]]></description>
			<content:encoded><![CDATA[<p>Creating the list of songs was fairly straightforward. Now I need to show the words on the screen. I said in the previous post that I raised an event when the songslist selection changed. In the window, actually another control, I add a handler to listen to the event. Actually, Visual Studio does most of it for you if you press Tab a few times.  After the mandatory InitialzeComponent is called in the control&#8217;s constructor I have this line of code:<br />
<code><br />
EventHub.SelectSong += new EventHandler<SongSelectionEventArgs>(EventHub_SelectSong);<br />
</code><br />
EventHub is the class that contains my event declarations. Within Visual studio you just type<br />
<code><br />
EventHub.SelectSong +=<br />
</code> and hit the Tab key twice. VS completes the line and creates a method for you. You just fill in the code in the method.<br />
<code><br />
void EventHub_SelectSong(object sender, SongSelectionEventArgs e)<br />
      {<br />
         song= tasks.GetSongLyrics(e.Song);<br />
         XmlTextReader reader = new XmlTextReader(new StringReader(song.Lyrics));<br />
         FdrSong.Document = XamlReader.Load(reader) as FlowDocument;<br />
         FdrSong.Document.Background = Brushes.WhiteSmoke;<br />
      }<br />
</code><br />
The song was added to the SongSelectionEventArgs when the song was selected from the list. We then go back to the database to grab the lyrics. Originally I had tried to set the background colour of the FlowDocument Reader, Fdr. This didn&#8217;t work. The background applies to the document itself, which makes sense when you think about it, I just wasn&#8217;t thinking about it clearly enough.</p>
<p>Now to get the words to show on a second monitor. In Winforms there is a class System.Windows.Forms.Screen. One of its properties is AllScreens which is an array of all the screens on the system. There is no corresponding class in WPF, and so no easy way to show the FlowDocumentReader on a second monitor.</p>
<p>So what are the options? One is to host a windows form inside WPF and have that form host the WPF control. I have read that there are problems with that. I think, although I haven&#8217;t tried yet, that I would need to set the focus to the second monitor to interact with it. And I don&#8217;t want to do that. I want to drive the second monitor from the primary monitor.</p>
<p>The second option is to go back and do everything in Winforms. That is appealing. I am comfortable with Winforms. But there are two problems. The RichTextBox in winforms doesn&#8217;t give me the functionality that I can get inWPF. The second problem is that this was an excuse to learn more about WPF.</p>
<p>The third option, and the one that I am going to try now, is to build the application in Winforms but have a number of controls built in WPF. Winforms can host WPF controls, and this will mean that I will have to brush up on interoperability. Any word with that many syllables sounds dangerous, but it seems to be the way to go.</p>
<p>I now need to see how much of what I have already done can be salvaged, and how much must be re-written. But that is often the case in any software project.</p>
<p>One issue I haven&#8217;t dealt with is unit testing. And the first rule of development is that if it isn&#8217;t tested then it is broken.</p>
<p>So far, I have written very little code. Most of it has been the UI. With the exception of ensuring thatI can put a Section tag into a flowdocument, the commands on the Rich Textbox are all built-in, there is no code. But there will be soon when we change fonts and colours. There is some code to access the database. I don&#8217;t like running unit tests against the database too often, but I have written tests for these in a separate project, but it means running against a database in a couple of different states, so once the code is tested we won&#8217;t touch these again until we want to do some end to end testing near the completion of the project. Of course, if I add more database access code then I will have to write more tests.</p>
<p>The point is that there is no business logic yet. There may be soon.</p>
<p>Another issue is Linq. LLBL Gen does have Linq to SQL built into the latest version. I haven&#8217;t used it, and so far I have found no need. When I get some time I will explore it some more. However, I have used Linq in other projects, and I may use it here. For example, when I get a collection of songs into the list box I might want a search function. I have previously done this with Linq. If the collection, or the TypedList, or Dynamic List, or whatever it is that you use to populate the list box isn&#8217;t so big that there is no problem in getting all the data, and it needs to be a lot of data before it becomes an issue, then you may want to filter it down. For example, a list of names may be filtered by the initial of the surname. Linq is easy to use against an existing collection and I may do this.</p>
<p>The reason I haven&#8217;t done anything so far is that, at this stage I am uncertain how I want to search. One way is to have a textbox for the search. When a user types in letters the list of songs can be filtered. But there are a couple things that I haven&#8217;t decided on. Do I want to start filtering on each keypress? Or do I want the user to enter a string and then, perhaps hit <Enter> to initiate the search? Even more fundamentally, do I want to search on titles that beging with the search string or titles that contain the search string? These are usability issues that I haven&#8217;t decided yet. I think I am going to have to build the bulk of the app and then see how I want to use it. Or maybe I will come to a decision before that. At the moment it doesn&#8217;t cause me any concern, we will deal with it when we have to.</p>
<p>So now it is off to look at building a winforms application with some WPF components.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/29/another-step-backward/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Filling the Songs ListBox</title>
		<link>http://midnightmuse.com.au/2008/08/29/filling-the-songs-listbox/</link>
		<comments>http://midnightmuse.com.au/2008/08/29/filling-the-songs-listbox/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 23:45:05 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Business]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=128</guid>
		<description><![CDATA[It is time to show a collection of songs]]></description>
			<content:encoded><![CDATA[<p>After the last post I saved some songs and built a list box to hold the song titles. I should say a little about that. These days I don&#8217;t write any SQL. I know that I still can write it because I wrote a simple SQL query for someone else a week or so ago. But I let someone else do it. By that I mean that I use an Object Relational Mapper. In my case I use <a href="http://www.llblgen.com">LLBL Gen Pro</a>.  There are others out there but I have been using this for a few years now and I quite like it.</p>
<p>Some would suggest that using an O/RM is overkill for such a simple database schema. And it is. At this stage I don&#8217;t even know if I am going to use a database. But I have gotten so used to querying my databases through LLBL Gen that it is easier to just use it.</p>
<p>To get a collection of songs is pretty easy.<br />
<code><br />
public EntityCollection GetAllSongs()<br />
{<br />
EntityCollection songs= new EntityCollection(new SongEntityFactory());<br />
ExcludeFieldsList exFields = new ExcludeFieldsList();<br />
exFields.Add(SongFields.Lyrics);<br />
ISortExpression sorter = new SortExpression(SongFields.Title | SortOperator.Ascending);<br />
using(DataAccessAdapter da = new DataAccessAdapter())<br />
da.FetchEntityCollection(songs,null,0,sorter,null,exFields);<br />
return songs;<br />
}<br />
</code><br />
This code is pretty straightforward. Line one creates a new collection of songs. The sorter says to sort on the Title field. LLBL Gen allows to different modes of data access: Adapter and Self-servicing. Adapter uses a DataAccessAdapter to fetch the entities. Self-servicing has a collection class for each type of entity and there are methods on the collection class to get the entities to fill the collection. This is simple enough to probably warrant using Self-Servicing, but again, I have been used to using Adapter, and so this is what I went with. It may change later, but that is not really an issue. At this stage I just want to be able to populate a list box.</p>
<p>The second line in the method is interesting. I said earlier that I am still uncertain if I will be using a database. But if I stick with it, I don&#8217;t know if I will populate the listbox with an entity collection. Performance wise it would probably make more sense to use a read only list. LLBL Gen will create TypedList classes for you, or you can generate your own dynamic list. But at the moment I just created a collection to see how it all hangs together. But doing this means pulling in a lot of data from the database that I don&#8217;t want. The database table for song has fields for Title, Author and Lyrics. The Title and Author are varchar(50) at the moment. That was the default size in SQLServer and it will do to start with. Lyrics, however, is much bigger. How big should it be? I don&#8217;t know yet, so I have set it to varchar(Max). The second line in the method says don&#8217;t get back the lyrics field. When I want to show the lyrics for a particular song I call another method to get the words.</p>
<p>So I saved a few songs and populated a listbox. Populating the listbox in WPF is pretty easy. I used a mixture of procedural code and xaml to accomplish it. My methods for accessing the database, that is, the code above, is held in a separate project called Tasks, for want of a better name. The songs listbox is held in a separate WPF control called SongListCtrl. To fill the listbox if use the following method<br />
<code><br />
private void FillSongsListBox()<br />
{<br />
songs = tasks.GetAllSongs();<br />
songsListBox.ItemsSource = songs;<br />
}<br />
</code><br />
The ItemsSource property binds the songs collection to the songsListBox. In the Xaml code I set the DisplayMemberPath to Title and that is what is shown in the listbox.</p>
<p>Now comes the hard part. I have a list of songs and I need to display the words. The first thing is to go back to database and get the Lyrics for that song, as explained earlier. I also created a new class SongSelectionEventArgs, which derives from EventArgs and has a property, SongEntity. The EventHandler is done with the standard generic event declaration<br />
<code><br />
public static event EventHandler SelectSong;</p>
<p>public static void OnSelectSong(object sender, SongSelectionEventArgs e)<br />
{<br />
if (SelectSong != null)<br />
SelectSong(sender, e);<br />
}<br />
</code><br />
Now the window that contains the SongListCtrl can listen to changes in the listbox selection. This is all pretty standard stuff. In WPF it works exactly the same way as in winforms. Although there are other ways to handle behaviour, for example using commands as I mentioned in the last post.</p>
<p>It is now time to show the songs on the monitor, and on a separate monitor, which in production will be a projector. This was a major problem as we will see in the next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/29/filling-the-songs-listbox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Editing Songs</title>
		<link>http://midnightmuse.com.au/2008/08/27/editing-songs/</link>
		<comments>http://midnightmuse.com.au/2008/08/27/editing-songs/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 01:36:25 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=123</guid>
		<description><![CDATA[I just want to edit some text. How can it be so hard?]]></description>
			<content:encoded><![CDATA[<p>After the last post I had some words on the screen. I now need to be able to split them into verses and edit them.</p>
<p>The whole point of a FlowDocument is that it flows. That is, it decides itself when to break into a new page. But I wanted to override this and insert page breaks at the end of each song verse. I spent hours googling and looking at the Microsoft examples One forum response to someone else&#8217;s similar requirement suggested that it couldn&#8217;t be done. I wasn&#8217;t prepared to accept that.</p>
<p>I eventually found that it could be done.</p>
<p>A flowdocument consists of a number of TextElement objects. TextElement is an abstract class and is the base for two abstract classes: Block and Inline. The most common derived class is Paragraph, which is derived from Block. Within a paragraph you can place Inline derived objects such as Span and TextBlock. A typical flowdocument is made up of a number of paragraphs. The flowdocument has a Blocks collection which has a number of methods for navigating through the document.</p>
<p>The Block derived class I needed was Section. A section contains one or more paragraphs. You don&#8217;t need a section but you can insert one if you want. What was important for is that section has a boolean property BreakPageBefore, so now I could insert a page break. So I tried the following code:<br />
<code><br />
Section section = new Section();<br />
          section.BreakPageBefore = true;<br />
          rtb.Document.Blocks.Add(section);<br />
</code><br />
It didn&#8217;t quite work.</p>
<p>This code adds the section, but it adds it to the end of the document, not at the position in the document where the caret is currently positioned. It also doesn&#8217;t move the caret to the new section.</p>
<p>That is OK if I just want to add a new verse at the end, so it is the start of something useful. So I will first deal with getting the insertion point into the new section. In order to add new text I need a paragraph to insert it into. When you press Enter while editing the RTB a new paragraph is inserted automatically. But it isn&#8217;t if you create it programmatically. So the first thing to do is to create a new paragraph and move the insertion point:<br />
<code><br />
rtb.Document.Blocks.Add(new Paragraph());<br />
           EditingCommands.MoveDownByParagraph.Execute(null,rtb);</code><br />
The first line creates a new paragraph. The second line is a built-in command. WPF has a number of these as I mentioned in a previous entry. The first argument, according to the documentation, is ignored by most commands. I haven&#8217;t come across a command yet which uses it, perhaps I will at some stage. It should be set to Null. The second argument is the object which will use the command. The object must implement the IInputElement, and Rich Textboxes do this. The RTB has implementations for a bundle of these commands. So, in effect, I have created a paragraph and moved the insertion point into the new paragraph.</p>
<p>The next problem is to insert a new section with a page break anywhere in an existing flowdocument. This took me a long time to find out how to do. The solution, when I eventually sorted it out, is very simple.</p>
<p>A flowdocument contains a lot of stuff other than plain text. That is the whole point of using a Rich TextBox. In a textbox you can set a selection point with texbox.SelectionStart. There are other methods such as Select, for selecting text using an integer for the start and another integer for the length. There is the SelectedText property and other methods as well. The whole point is that text is stored as a string which is a character array. But in the Rich Textbox there is other stuff in the string, such as pargraph and section tags, formatting tags etc. So using integers to move around text doesn&#8217;t work.</p>
<p>To resolve this issue MicroSoft uses a TextPointer object to represent position within a FlowDocument. The TextPointer will tell us where we are in the document:<br />
<code><br />
//Get the caret position<br />
Textpointer pointer = rtb.Selection.Start;<br />
//Get the paragraph which contains the caret<br />
Paragraph paragraph = pointer.Paragraph;<br />
//Insert the new section after the current paragraph<br />
rtb.Document.Blocks.InsertAfter(paragraph,section);<br />
</code></p>
<p>Almost done. To test all of this I put a button on the form which I clicked to insert a new verse. The button will remain, but we really need a keyboard accelerator. At the moment, to insert a new paragraph you just hit <Enter>. I think that is what a user would expect. I decided that to insert a new page I should follow the convention used in Microsoft Word and use Ctrl + Enter. WPF uses the concept of KeyGesture There are couple of ways to wire this up. I know I am going to need some more key gestures for editing so I first created  private field of type Dictionary to hold all my key getstures.<br />
<code><br />
private Dictionary<KeyGesture,RoutedEventHandler> gestures =<br />
   new Dictionary<KeyGesture,RoutedEventHandler>();<br />
</code><br />
When the Edit Control loads it calls a method to add gestures, in this case there is only one at the moment.<br />
<code><br />
gestures.Add(new KeyGesture(Key.Enter,ModifierKeys.Control),AddNewVerse);<br />
</code><br />
This line of code says that the Gesture compring the Control Key + the Enter Key will call the AddNewVerse method, which is the method which contained the earlier code for inserting paragraphs and sections.</p>
<p>I now need to hook this up to the KeyDown event of the Rich TextBox.<br />
<code><br />
private void rtb_PreviewKeyDown(object sender, KeyEventArgs args)<br />
      {<br />
         foreach (KeyGesture gesture in gestures.Keys)<br />
         {<br />
            if (args.Handled) return;<br />
            if (gesture.Matches(null, args))<br />
            {<br />
               gestures[gesture](this, args);<br />
               args.Handled = true;<br />
            }<br />
         }<br />
      }</code><br />
In this code args is of type KeyEventArgs. The code looks through the dictionary of key gestures seeking a match. If it finds a match it executes the method in the dictionary. It then sets the handled property to true so that it won&#8217;t do anything else. Otherwise it would raise the event for the Enter key and insert another paragraph. I could let it do that and not insert the paragraph myself in the AddNewVerse method. But if I add more gestures I could run into problems. I think it is safer to tell it explicitly what you want done.</p>
<p>And that is it for this time.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/27/editing-songs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Rich Text Box</title>
		<link>http://midnightmuse.com.au/2008/08/22/the-rich-text-box/</link>
		<comments>http://midnightmuse.com.au/2008/08/22/the-rich-text-box/#comments</comments>
		<pubDate>Fri, 22 Aug 2008 08:10:14 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=114</guid>
		<description><![CDATA[The Rich Text Box in WPF is a different animal than the one in winforms]]></description>
			<content:encoded><![CDATA[<p>I want to edit my songs, and in the editing I want to put some formatting. The Rich Text Box is the control to do this. Even in Winforms, the Rich Text Box would be the way to go. But in WPF it behaves differently.</p>
<p>The first thing that you notice is that the Rich Text Box (RTB from now on) does not have a text property. It contains a Flowdocument. A flowdocument is a new concept in WPF. It represents a document which can flow, naturally enough. It will take up all the available space on a page and flow onto extra pages. This, of course, all depends upon the size of the pages. A flow document is read with either a FlowDocumentReader, a FlowDocumentPageViewer or a FlowDocumentScrollViewer. The FlowDocumentPageViewer shows the document page by page. The FlowDocumentScrollViewer shows the entire document in continuous scrolling mode. The FlowDocumentReader allows you to choose either of these two modes or two pages at a time. With each of these you can adjust the zoom on the page. So they are fairly flexible.</p>
<p>A FlowDocument is just a piece of xaml code. The text is contained within paragraph tags in the xaml.</p>
<p>The nice thing about the RTB is that it has all the editing functions built in. Many of these are already hooked up to keyboard shortcuts. Placing the cursor over a word and hitting Ctrl+B will make the entire word Bold. EditingCommands has more methods than you would ever want to use. There is really very little need to add much, or anything, in order to have a fully functioning editor. WPF uses commands to attach behaviour to controls. There is also the standard events, and another new concept, triggers. We will look at these in a later post when we get to wire everything up.</p>
<p>One thing which did arise as a result of playing with this stuff was the question of how I would arrange and store the data. I had earlier said that I would prefer to store the data in a database. My original thinking was that I would store an entity called song, and a related entity verse. A song could have one or many verses. In that scenario it made sense to use a database.</p>
<p>Upon reflection I am close to abandoning that idea. I am thinking that each song would contain all its lyrics in one xaml file. If that is the case then the database would only have one table and I am starting to think that there is no need for it.</p>
<p>I may still change my mind about the song and verses, we will see how it pans out. But for, since I have the database set up I am using it, but will probably abandon it later. To read the flowdocument from the database I need a memory stream. If I go with a file system instead of a database I will just use a file stream. So there is no big change.</p>
<p>One area where I did run into trouble was getting the flowdocument from the RTB. This bit is easy:<br />
<code>FlowDocument doc = rtb.Document;</code><br />
No problem, I now have the flowdocument contained within the RTB. But what can I do with it. I can&#8217;t cast it to a string to save it, and if I want to save it to a file then I am out of luck. After a bit of searching on the web I found that I could do this:<br />
<code><br />
          TextRange range = new TextRange(rtb.Document.ContentStart,rtb.Document.ContentEnd);<br />
          MemoryStream stream = new MemoryStream();<br />
           range.Save(stream,DataFormats.Xaml);</code><br />
In this case the range is from the beginning of the document to the end. range.Save saves the range into the new stream using the DataFormats provided. There are a number of DataFormats, including Xaml, XamlPackage and Rtf. However, doing this introduces a lot of unnecessary cruft into the string. I then found a much simpler way to save:<br />
<code> string lyrics = XamlWriter.Save(rtb.Document);</code><br />
And this only saves the flowdocument itself into the string. There are overloads so you can save to a stream, for example a file stream. I found doing this that I was able to do away with my memorystream altogether.</p>
<p>Reading the flowdocument from the database was nearly as easy:<br />
<code><br />
           XmlTextReader reader = new XmlTextReader(new StringReader(song.Lyrics));<br />
           FlowDocument doc = (FlowDocument) XamlReader.Load(xmlTextReader);<br />
           rtb.Document = (FlowDocument)XamlReader.Load(reader);</code><br />
So using the database is easy. Whether I will keep it is another question.</p>
<p>The next step is parsing the flowdocument to split it up into verses. That is a job for tomorrow.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/22/the-rich-text-box/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>More on the UI</title>
		<link>http://midnightmuse.com.au/2008/08/20/more-on-the-ui/</link>
		<comments>http://midnightmuse.com.au/2008/08/20/more-on-the-ui/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 22:39:35 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=112</guid>
		<description><![CDATA[Presentation Foundation and Winforms can be used together]]></description>
			<content:encoded><![CDATA[<p>One thing I hadn&#8217;t thought of yesterday when I wrote about the UI is the possibility of using WPF and winforms together.</p>
<p>I have read, although I haven&#8217;t tried it yet, that winforms can host WPF, and vice versa. At some stage through this project I will run an experiment on that. It isn&#8217;t urgent yet, but it is something that is worth keeping in mind.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/20/more-on-the-ui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Start with the UI</title>
		<link>http://midnightmuse.com.au/2008/08/19/a-start-with-the-ui/</link>
		<comments>http://midnightmuse.com.au/2008/08/19/a-start-with-the-ui/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 05:38:13 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=89</guid>
		<description><![CDATA[Time to make an initial start with the User Interface]]></description>
			<content:encoded><![CDATA[<p>I often look back at the old days of programming. A computer couldn&#8217;t do much so not much was expected. But things have changed. I now spend more and more time trying to build a decent looking user interface. I read a few weeks ago, and I wish I could find the quote, something along the lines of <em>A designer shoots bullets, a developer throws them.</em> I am not a designer, so I am throwing bullets at the screen rather than shooting them, and I am sure that they are having the same effect as throwing them – not much.</p>
<p>Nevertheless, you need a UI of some sorts, so I built one. Here is a screen shot of where it is at now.<a rel="attachment wp-att-90" href="http://midnightmuse.com.au/2008/08/19/a-start-with-the-ui/ribbon/"><img class="aligncenter size-medium wp-image-90" title="Ribbon" src="http://midnightmuse.com.au/wp-content/uploads/2008/08/ribbon-300x60.jpg" alt="First attempt at ribbon menu" width="600" height="60" /></a></p>
<p>There are a few things to say about this ribbon bar. Microsoft has produced a Ribbon Bar but the licensing is far too restrictive to be of much use. In any case, they don&#8217;t have one for WPF. So you have to build your own. This obviously needs more styling before it is completed, but we will look at some of the details of the ribbon as it stands at the moment.</p>
<p>First, it is a separate control. You could build it all on the main form,  but I think it is better to separate your controls into separate classes – it is standard OO good practice. At the moment I am trying out Expression Blend 2.5 June 2008 Preview. I have had a few issues with it, it sometimes hangs or crashes Visual Studio. But I am running the Beta of Visual Studio 2008 SP1, and I think the release version of SP1 might fix this. This was released in the last few days.</p>
<p>Expression Blend is primarily a designer&#8217;s tool. And I find it easier to do some of the work in Blend and some in Visual Studio. Having two large monitors really helps if you are using these two together.</p>
<p>When  you create a new user control Blend defaults to using a grid as the layout container. In this case I could have used a different container, but it doesn&#8217;t really matter, at least I don&#8217;t think it does. I left it as a grid. Within the grid I have a Tab Control, and I will add some styling to the tab headers when I get to the stage of trying to make it pretty. At the moment the only tab with any content is the <strong>Songs</strong> tab because this is where all the editing will go.</p>
<p>Within this tab control I have a Stackpanel aligned horizontally, These contain File, Edit, Font and Arrange sections. Each of thse sections contains a grid. The first two, File and Edit, have four columns and three rows. The bottom row contains a border which contains a TextBlock which spans all the columns and is horizontally aligned to the centre. The border is set with a colour, a thickness and a radius for the rounded corners.</p>
<p>In the top row, in each column, is a button. The button contains an image. And below the button is a Textblock with the text of the control, eg New, Open etc. The button and the textblock are also contained within a border which spans all four columns and two rows, and has a border colour and thickness, and rounded corners.</p>
<p>The nice thing about WPF is that any control, well most controls, can contain almost any content you want. In winforms a button had a text property. If you wanted a button with an image you needed to create your own button by subclassing the button class, or building some button like properties and events into an image. WPF is different. Controls have a property called Content and you can put almost anything into it. For example, you could have the content of a button be another button. I don&#8217;t know why you would do that, but you could. You are also able to edit the individual components of the button to style it in all manner of ways. There is a lot information about WPF styling on the web.</p>
<p>The font section contains some interesting features. The first combo box is a list of fontstyles. This is the xaml to set the fontstyle combo.<br />
<code><br />
&lt;ComboBox IsSynchronizedWithCurrentItem="True"<br />
                                  ItemsSource="{x:Static Fonts.SystemFontFamilies}"<br />
                                  x:Name="cmbFont" HorizontalAlignment="Stretch"<br />
                                  VerticalAlignment="Center" Margin="10,0,5,0"<br />
                                  BorderBrush="{x:Null}" Style="{DynamicResource ComboBoxStyle1}"<br />
                                  Width="Auto" FontSize="14"&gt;<br />
                            &lt;ComboBox.ItemsPanel&gt;<br />
                                &lt;ItemsPanelTemplate&gt;<br />
                                    &lt;VirtualizingStackPanel /&gt;<br />
                                &lt;/ItemsPanelTemplate&gt;<br />
                            &lt;/ComboBox.ItemsPanel&gt;<br />
                            &lt;ComboBox.ItemTemplate&gt;<br />
                                &lt;DataTemplate&gt;<br />
                                    &lt;TextBlock Text="{Binding}" FontFamily="{Binding}"<br />
                                               FontSize="14"<br />
											   Height="20" /&gt;<br />
                                &lt;/DataTemplate&gt;<br />
                            &lt;/ComboBox.ItemTemplate&gt;<br />
                        &lt;/ComboBox&gt;</code></p>
<p>There are a few things to notice here. The Items source binds the combo box to the System Fonts. Then the Itemspanel declares a template, ItemsPanelTemplate which contains a Virtualizing StackPanel. This means that items are arranged in a stack. You can leave this out and it will include it by default, but not until after it has retrieved all the data. By specifically declaring the Virtualizing Stack Panel the list loads faster. Although I seem to remember a warning about this. I need to look further into it. The interesting thing is the TextBlock. The ItemTemplate says that the items in the combo box will be rendered using a Textblock. The text of the text block is bound to its parents datasource, hence Text=&#8221;{Binding}&#8221; And the font used in the Textblock is bound to the font family of the datasource. So each item in the combo box is rendered in the specific font.</p>
<p>Combo boxes and List boxes are much more versatile in WPF than winforms.</p>
<p>A similar thing happens with the font colours. There is a button whose event handler is wired to a popup control. When the button is clicked the popup appears. The popup contains a listbox. A separate class contains a dictionary of colours. Specifically I have declared a Dictionary&#038;ltstring, Brush&gt;/. Brush is used in WPF to declare the colours which will be used to render items, paint backgrounds, borders etc. So the string is the colour name, and the brush is, for example Brushes.Black.  When the listbox is populated a new ListBoxItem is created for each item in the dictionary. The Item is the string and the colour of the item is the Brush colour.</p>
<p>The next thing to do is to wire up some events. More on that next time.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/19/a-start-with-the-ui/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presentation Part 2</title>
		<link>http://midnightmuse.com.au/2008/08/18/presentation-part-2/</link>
		<comments>http://midnightmuse.com.au/2008/08/18/presentation-part-2/#comments</comments>
		<pubDate>Mon, 18 Aug 2008 04:27:12 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=88</guid>
		<description><![CDATA[Presentation Software &#8211;design considerations]]></description>
			<content:encoded><![CDATA[<p>It is time to get down to the details of what the Presentation Application &#8211; let&#8217;s call it <em>Presenter</em> for now &#8211; will do. This is a first look at the required functionality</p>
<ul>
<li>Show list of all songs and other types of items. I will call everything a song for the moment.</li>
<li>Allow editing of songs, adding, deleting and modifying.</li>
<li>Show the songs on a separate screen, usually through a projector.</li>
</ul>
<p>That&#8217;s a reasonable start. But even this short list has a number of ramifications. </p>
<ul>
<li>Obviously we need a UI of some sort, with a menu, and, I think, associated keyboard commands.</li>
<li>Where do we store the data, and in what format?</li>
<li>How will I program the application?</li>
<li> There is also the more fundamental question. We need to determine where the application will run.</li>
</ul>
<p>I will deal with the last point first.
</p>
<p>I am writing this primarily for myself. I program in Windows, and I use Windows. So it is going to run on Windows. However, if it works OK it would be nice if others could use it. That being said it makes sense to ensure that the app will run on XP and Vista. Anything earlier than XP is not worth worrying about. I know some people are still using Windows 98, but there are not too many of them left. I have had no experience with Windows 2000, and I am not sure of the differences and I am not going to bother finding out.</p>
<p>My current programming environment of choice is .NET. I use 3.0 or 3.5, but I can target the 2.0 framework, although that is not a primary concern. If anyone wants to use this there is a fair chance that they will have to download the framework, or get it somewhere so it doesn&#8217;t matter much which one they get. My preferred language is C# so we are set. Almost.</p>
<p>The most important decision concerning the environment is this $#8211; do I write a standards winforms application or a Windows Presentation Foundation (WPF) application? There are arguments on both sides. I have been writing winforms for years and am pretty comfortable with it. WPF, on the other hand has a lot going for it. It is likely to be the standard for Windows client applications in the future. There is a lot you can do with it. And, while I have been playing around with it, it is still fairly new to me. Part of the problem is that much of the design is done in xaml (Extensible Application Markup Language) which is xml with the appropriate namespaces, more or less. But it does follow the rules of xml. I am more comfortable with c# code than xaml. You can, of course, write all the WPF stuff in c#, but some of it would be a nightmare to do. It is a lot easier in xaml. So which to choose?</p>
<p>The answer really comes down to what I want the application to look like. There will be a few screens for editing songs and sorting out which song to display, but essentially the application is a presenter on a separate screen. How am I going to show the songs on a screen? There are probably two ways to do this &#8211; there may be more but I can&#8217;t think of them off the top of my head. I could use HTML and show the songs in a browser. Or I could put the songs in a Rich Textbox. HTML has its appeal, but this is still a client application. I don&#8217;t, at this stage, want to go down the web route. A Rich Textbox will show all the formatting and it will also allow the editing to be done in a similar control. I am leaning towards the Rich Textbox.</p>
<p>Winforms and WPF both have Rich Textbox controls. But they work differently. In Winforms the content is held in RTF (Rich Text Format). To save it to a database I think I would need to store the data in a binary field and I think it would be pretty big. There is a lot of formatting to be saved along with the text. I could also save it as an rtf file, but these are also pretty big. But this is an option.</p>
<p>WPF, on the other hand, stores its Rich Textbox content in a new format call a Flowdocument. This has a number of advantages. First, it means that we don&#8217;t, in fact, need a Rich Textbox to display the data. The song can be edited in a textbox but then displayed using a Flowdocument reader. Alternatively, the document can be transformed into a Fixeddocument and displayed using a document reader. I&#8217;m not sure if this is a help or not, but it may be. Secondly, the flowdocument is just xaml, and so it can be stored as a xaml file or stored in a database. I&#8217;ll get to the database shortly. </p>
<p>So, with either winforms or WPF I can store the songs as either files, or as fields within a database. With WPF, however, regardless of how they are stored, the songs will be smaller, and I think that will be a benefit for load times. So which one. WPF gives me more options at how I display. It gives me more eye candy on the UI. And it is an environment that I really need to come to grips with. So WPF it is. I may regret this decision and change my mind later. Against this, I do have some nice UI stuff for Winforms. I use the <a href="http://www.devexpress.com/">DevelopExpress</a> suite of tools for UI in winforms and they are pretty good. If I decide that WPF was a mistake I can go back and build the UI in winforms. The logic will be the same regardless.</p>
<p>The final question is where to store the songs.  I much prefer the idea of storing them in a database than in files. If it was a matter of just storing text then I don&#8217;t think there is any question. But this is formatted text. So text files may be a better option. If we go the database route there is then the question of what type of data field do we store them in. SQLServer, and some other databases, I believe, have an xml datatype. Xaml is xml, so I could use the xml data type. But the xaml is also just a string. In order to get it into and out of a Rich Textbox or a FlowDocument, I think I would need a stream. That may give rise to the question of encoding. .NET uses UTF16 for characters. Does that mean that if I would need to store as nvarchar rather than varchar? At this stage I have no idea &#8211; this is all new to me, I have rarely worked with streams, except for opening and closing files, and updating them etc. But it isn&#8217;t a big problem, it is just a matter of performing a few experiments.</p>
<p>But, in any case, it doesn&#8217;t matter now. I know that I can store the data in either a database, in some form, or else in files. So I will proceed on the basis that I will be reading and writing flowdocuments, where I will read them from or write them to is an implementation issue that can be put off until we need to address it.</p>
<p>The next step will be some early design work on a basic UI. It will not have to do everything yet, but I want to get a feel for what the application will look like so that I can assure myself that it will work, from a users point of view. That will be the subject of the next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/18/presentation-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presentation Software</title>
		<link>http://midnightmuse.com.au/2008/08/16/presentation-software/</link>
		<comments>http://midnightmuse.com.au/2008/08/16/presentation-software/#comments</comments>
		<pubDate>Sat, 16 Aug 2008 04:26:05 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Presenter]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/?p=87</guid>
		<description><![CDATA[PowerPoint has its shortcomings, but so do most of the other options]]></description>
			<content:encoded><![CDATA[<p>First some background. I attend a church which, like many others, uses a projector to show the hymns or songs which are to be sung. We also project other parts of the service, some prayers and some items which require a response from the congregation.</p>
<p>
Many churches, including ours, have followed a similar route. We start out with books. In our case, being an Anglican Church, that consists of a hymn book and a prayer book. There are also pew Bibles so that the congregation can follow along when the Bible passage is read. This, in itself, is a problem. You have three books to juggle, and for some people, especially newcomers, it is difficult to know which book you are supposed to be reading and where in that book you are up to. We still do this at our fairly traditional 8:30 am service.</p>
<p>
One church I used to attend in Southern NSW printed the whole service each week. This solved the problem of books, but it meant a lot of printing and a lot of wasted paper. They realised that this was not a long term solution and were looking for an alternative.</p>
<p>
After using books, the next step in the progression, for many places was an overhead projector. There was still a lot of time spent in preparing the slides, but they could be re-used. In many churches just the songs were on overhead.</p>
<p>
But now we are in the technological age and we have <a href="http://office.microsoft.com/en-gb/powerpoint/default.aspx">PowerPoint.</a></p>
<p>
I must admit, at the outset, that I hate PowerPoint with a vengeance. That&#8217;s not exactly true &#8211; it isn&#8217;t PowerPoint, per se, that I hate, it is the way it is used. Too often PowerPoint has been used as a substitute for good preparation. PowerPoint itself is pretty good, it is just used badly. I also wonder if it is always used legally, but that is another issue.</p>
<p>What is the problem with PowerPoint for church service presentation? First, it is slow to change slides, although I can live the speed. But there is a noticeable lag when changing from one slide to the next. Second, you are locked into the presentation that you have prepared. So often at church someone comes to me just before the service starts and says that we need to make a change. Perhaps a musician has a problem with one of the songs. Or you need to insert a couple of new slides. This can all be done, but it takes time. The final problem, which isn&#8217;t the fault of PowerPoint, is that there are so many different animation effects that can be used to move from one slide to the next. You can have fade and slide and checkerboard and up and down and left and right blinds, and all of these come in a variety of styles. Functionality is good. Flexibiity is good. But just because you can do something doesn&#8217;t mean that you should. And some PowerPoint presentations look horrible. PowerPoint used well by someone with some graphic design skills is great, usually it is just rubbish.</p>
<p>So what are the alternatives? There are a number. We have been trying out <a href="http://www.zionworx.org.uk/">Zionworx</a> and it isn&#8217;t too bad. It is also free. There are a number of commercial packages around, one of the better know ones being <a href="http://www.mediashout.com/">MediaShout</a>. I had a look at the express version, there is also a starndard version. Express version costs $229 and the standard version costs $429. I think these are $US prices. The Standard version may do what I want, but the express version does not. Neither does Zionworx, nor a number of other packages that I tried. Most of the others cost serious dollars, Zionworx seems to be the only free version I could find.</p>
<p>I don&#8217;t mind paying for software. I spend a lot of money on software. But there were two problems with buying a commercial package. The first is that I don&#8217;t want it, the church does, and I think that I would have had a hard time getting them to spend around AUD$500 on presentation software. Second, I wouldn&#8217;t spend that kind of money on something that doesn&#8217;t do what I want.</p>
<p>What is the problem with these packages? Unlike PowerPoint they don&#8217;t give enough formatting options. For example, when we display a song we just want the words to appear in a large readable font. All the packages do this. They provide a number of formatting options, fontface, size, background colour or a background graphic, foreground colour. But the formatting applies to the whole item being displayed. We often have some responsive items. The service leader will say something and the congregation will respond. In PowerPoint we used a white foreground for the service leader&#8217;s words, and a yellow foreground for the congregation&#8217;s response. In Zionworx I cannot do this.</p>
<p>The reason I can&#8217;t do it is because the displayed items are held in a database in text format. The styling is applied to the whole slide, or item being presented. Keeping the data in a database is, in my mind, the right way to go. The data is pulled from the database in one go and is immediately available. The rendering on the screen is very fast. There is no discernible delay in moving from one screen to the next. But it cannot be formatted at a level of granularity that suits us.</p>
<p>What to do? The only thing that a programmer would do in this situation is write my own. How did this pan out? See the next post.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2008/08/16/presentation-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Edit Contact</title>
		<link>http://midnightmuse.com.au/2006/04/28/edit-contact/</link>
		<comments>http://midnightmuse.com.au/2006/04/28/edit-contact/#comments</comments>
		<pubDate>Fri, 28 Apr 2006 08:31:39 +0000</pubDate>
		<dc:creator>Richard</dc:creator>
				<category><![CDATA[Hour]]></category>

		<guid isPermaLink="false">http://midnightmuse.com.au/2006/04/28/edit-contact/</guid>
		<description><![CDATA[<p>We need to edit contacts, and add new contacts. Here's how.</p>]]></description>
			<content:encoded><![CDATA[<p>It has been a while since my last post on this project. I have been held up with other things. But now it is time to move on.</p>
<p>The next thing to do is allow the user, in this case, me, to add, edit or delete contacts. Deleting is a subject which will need further investigation, but at this stage we will just allow simple deletes.</p>
<p>First we need a form. So we will create a new inherited form called ContactEditForm, and inherit from our BaseForm. On this form we will place some Labels, Text Boxes and Buttons, so that it looks like the diagram below.<br />
<img src="/wp-content/uploads/2006/04/ClientEdit.gif" alt="Contact Edit Form" /></p>
<p>There are a couple of things to do, all of them fairly straightforward.</p>
<p>First, we have to be able to get to the form, and this is done from the Contact Form, using the New and Edit buttons on that form. We will create a new Contact object in the ContactEdit form by declaring a new private instance of the Contact class, and make it accessible by creating a public property, called Contact. All very standard. The code looks like this:</p>
<pre>
   Private m_Contact as new ContactEntity

   Public Property Contact() as ContactEntity
      Get
          Return m_Contact
      End Get
      Set(ByVal Value as ContactEntity)
          m_Contact = Value
      End Set
   End Property
</pre>
<p>Visual Basic is very verbose, and in C# the code to do the same thing is much more concise. The good thing is that the IDE does most of the work for you.</p>
<p>To edit a contact the user needs to select a contact from the Listview control. Selecting the contact creates a new ContactEntity object and this object is passed to the ContactEdit form in the Set part of the property. So m_Contact, in the ContactEdit form is the same object as the Contact selected in the Contact form. The code to open the ContactEdit form also contains a command to set the Text of the ContactEdit form to <strong>Edit Contact</strong></p>
<p>If the New button is pressed then the ContactEdit form is created but the Text is set to <strong>New Contact</strong></p>
<p> and the <strong>IsNew</strong> property of the ContactEntity is set to true.</p>
<p>In either case the form is then opened with the Show method.</p>
<p>Next we need to set up databinding. In previous versions of VB databinding was a sad joke, but it is much improved in VB.NET. There are a couple of ways to set up databinding. I usually do it in code like this.</p>
<pre>txtSurname.Databindings.Add("Text",m_Contact,"Surname")</pre>
<p>And so on for each of the text boxes. Then it is merely a matter of attaching a Save method to the Save button, and a Delete method to the Delete button. We will revisit Delete at a later date when we consider validation.</p>
<p>The Close button has a form.close method attached and we are almost done.</p>
<p>There are two final things to do. The first is to set the Tab order which is done in the designer from the View menu. You merely select Tab Order from the menu and click each control in the order you wish to tab through them.</p>
<p>Lastly, we set the AcceptButton of the form to Save and the CancelButton to Close, and we are done.</p>
]]></content:encoded>
			<wfw:commentRss>http://midnightmuse.com.au/2006/04/28/edit-contact/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
