|
Architect or Cobbler?
Good code starts with good design |
|
about me
links
Blogs I follow
recent posts
archives
feeds |
Adding some Dialogs to ScribbleSaturday, November 18, 2006I'm going to add a dialog to the Scribble app so I can change the thicknesses of the pen lines. The dialog will look like this To do this you need a Window to represent the GUI, so I created a new Xaml file PenWidthDialog.xaml, gave it a border, a 4X4 grid, two text boxes and two buttons. The only work at this stage is to set the IsDefault and IsCancel properties on the appropriate buttons. I've also set the TabIndex and IsTabStop properties as you need to be able to tab through a dialog properly. <Border BorderThickness="2"> <Grid Background="LightGray"> <Grid.ColumnDefinitions> <ColumnDefinition Width="20" /> <ColumnDefinition Width="100"/> <ColumnDefinition Width="80" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="30" /> <RowDefinition Height="30" /> <RowDefinition Height="30" /> <RowDefinition Height="*" /> </Grid.RowDefinitions> <Label Grid.Column ="1" Grid.Row="1">Thin Pen Width</Label> <Label Grid.Column ="1" Grid.Row="2">Thick Pen Width</Label> <TextBox Grid.Column ="2" Grid.Row="1" Margin ="0,2,0,6" IsTabStop="true" TabIndex="0"> </TextBox> <TextBox Grid.Column ="2" Grid.Row="2" Margin ="0,2,0,6" IsTabStop="true" TabIndex="1" > </TextBox> <Button Grid.Column ="3" Grid.Row="1" Height="25" Width="70" Now I want to add the data bindings for the Pen Width, and immediately I realise I need a bit of refactoring, so I create a Pen class with 3 properties, ThinWidth, ThickWidth and InkColor. In my ScribbleCanvas class I create a new Pen and attach it to the canvas, and remove the old int properties that described thick and thin pens. Now change Scribble.Xaml to add an event handler for the menu PenWidths, by adding a Click property. The implementation of the event handler is a doddle, create a new PenWidth dialog object and show it using the ShowDialog method. This returns a bool? , so it is important you handle the null value that is returned if the user closed the dialog with the X. The simplest way to do this is to use the GetValueOrDefault method, which will convert a null to false. If you clicked OK then simply call the ChangePenWidths() method to propagate the changes to all canvases. Before you do this you have to set the static Pen property to the new Pen from the dialog. void OnChangePenWidths(object sender, RoutedEventArgs e){ PenWidthDialog pwd = new PenWidthDialog(); pwd.Owner = this; if (pwd.ShowDialog().GetValueOrDefault()) { ScribbleCanvas.ChangePen(); ChangePenWidths(); } } You can compile and run this, and though the dialog works, nothing will happen yet. The reason is obvious, we haven't bound the text boxes to any data, so we'll fix that right now. In WPF a control attempts to bind to a DataContext, and it will simply search up it's control tree till it finds a non-null DataContext and use this as the data source. Then you use the Binding element to attach to this context. The binding has a Path property, which describes the property in the context that you wish to bind against. In our case this will be the ThinWidth and ThickWidth properties of the Pen object that belongs to the ScribbleCanvas. To set up this data context I'm going to add an initialisation method that is invoked by adding the Loaded property to my Xaml, I'm also going to take the opportunity to add my WPFScribble namespace into the Xaml as I know I need it just now, as in: <Window x:Class="WPFScribble.PenWidthDialog" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:WPFScribble" Title="Pen Widths" Height="150" Width="300" ResizeMode="NoResize" Loaded="OnInit" > In the OnInit method I'm going to load the DataContext with the Pen object that I want to bind to. private void OnInit(object sender, RoutedEventArgs e) { this.DataContext = ScribbleCanvas.ScribblePen; } Finally you add the binding that will bind the properties to the text boxes. To do this you need to add either a Binding element to the Text property or attach a {Binding} statement directly to the text box. Both syntaxes are shown below. <TextBox Grid.Column ="2" Grid.Row="1" Margin ="0,2,0,6" IsTabStop="true" TabIndex="0"> <TextBox.Text> <Binding Path="ThinWidth" UpdateSourceTrigger="LostFocus" /> </TextBox.Text> </TextBox> <TextBox Grid.Column ="2" Grid.Row="2" Margin ="0,2,0,6" IsTabStop="true" TabIndex="1" Text="{Binding Path=ThickWidth}" /> You can run your application now, and changing Pen widths will work, well to a point. Open up the dialog and make the thin width 3 and the thick width a. Clearly this is a nonsensical value, but the GUI is quite happy to accept this. Oops, we need to add validation. WPF only comes with one validator the ExceptionValidationRule, which fires if an exception is thrown when updating the binding. This isn't good enough for our needs, so we need to create our own validator. To do this you subclass ValidationRule, provide any properties you need, such as a minimum and maximum value, and override the Validate method. This returns a ValidationResult, as shown in the code below. public class PenWidthRule : ValidationRule { private int _min; private int _max; public PenWidthRule() { } public int Min { get { return _min; } set { _min = value; } } public int Max { get { return _max; } set { _max = value; } } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { int age = 0; try { if (((string)value).Length > 0) age = Int32.Parse((String)value); } catch (Exception e) { return new ValidationResult(false, "Illegal characters"); } if ((age < Min) || (age > Max)) { return new ValidationResult(false, "Please enter an age in the range: " + Min + " - " + Max + "."); } else { return new ValidationResult(true, null); } } } You want the GUI to invoke the validation, so you need to add the validation rules to the Binding, as shown in the Xaml fragment below. If the validation fails, then the WPF framework will surround the text box with a red surround. <Binding Path="ThinWidth" UpdateSourceTrigger="LostFocus" > <Binding.ValidationRules> <src:PenWidthRule Min="1" Max="30" /> </Binding.ValidationRules> </Binding> You may want to have a custom validation message, to do this you need to change the style of the text box. We'll leave this till tomorrow :-) For now you can download the source for the project from here. # posted by James @ 3:43 PM # posted by @ 11:06 AM Ich entschuldige mich, aber meiner Meinung nach irren Sie sich. Ich biete es an, zu besprechen. viagra kaufen schweiz cialis preis [url=http//t7-isis.org]viagra preissuche[/url] # posted by @ 1:28 AM Ich denke, dass Sie nicht recht sind. Geben Sie wir werden es besprechen. levitra online levitra online viagra preis ?sterreich # posted by @ 9:04 PM Algo no sale asГ http://nuevascarreras.com/ cialis generico barato Bravo, hai appena visitato un'altra idea [url=http://nuevascarreras.com/tag/cialis-online/ ]cialis precios [/url] # posted by @ 12:57 AM Si sono errati. Io propongo di discuterne. Scrivere a me in PM, ti parla. [url=http://lacasadicavour.com/eriacta/ ]acquisto cialis generico [/url]A mio parere, si sbaglia. Cerchiamo di discutere di questo. Scrivere a me in PM. http://lacasadicavour.com/kamagra/ cialis acquistare Bravo, la tua idea ГЁ molto buona # posted by @ 3:25 PM no puede ser AquГ la falta? [url=http://csalamanca.com/tag/comprar-viagra/ ]comprar viagra sin receta en farmacia [/url] Y donde la lГіgica? http://csalamanca.com/tag/sin-receta/ viagra 100 mg precio # posted by @ 9:50 AM Post a Comment << Main blog page |
|
|
|