Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
About my WPF app to draw a Bolt Hole Pattern.
Message
De
28/07/2008 10:20:38
 
 
À
28/07/2008 04:50:00
Information générale
Forum:
ASP.NET
Catégorie:
Windows Presentation Foundation (WPF)
Divers
Thread ID:
01334102
Message ID:
01334519
Vues:
15
hmm... You were either up very late, or up very early based on the post time of your last reply.

Latest screen of BoltHole (it looks so much better in Vista than XP)..

http://www.jordanmachine.com/BoltHole_WPF.jpg


Added double-click to the ListView to show/hide any given hole
Added GridLines

Play with all the "+" and "-" buttons to watch it update.

Changing the HoleCount does a full clearining of the HoleList and Canvas, but changing all the other inputs simply updates the HoleObjects in the HoleList and then the Canvas automatically updates itsself.



Latest code below:
<Window x:Class="WpfApplication1.Window1" Name="winBoltCircle"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication1"    
    Title="Bolt Hole Pattern" Height="800" Width="800">

    <Window.Resources>
        <local:FormattingConverter x:Key="formatter" />
    </Window.Resources>

    <Grid Margin="5,5,5,5">
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="100"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="250" />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <ListView x:Name="CoordinateGrid" Grid.Row="2" Grid.Column="0" MouseDoubleClick="CoordinateGrid_MouseDoubleClick">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                </Style>
            </ListView.ItemContainerStyle>
            <ListView.View>
                <GridView >
                    <GridViewColumn Header="Number" DisplayMemberBinding="{Binding Path=HoleNumber}" />
                    <GridViewColumn Header="X Coord" Width="65">
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock 
                                Text="{Binding AbsX, Converter={StaticResource formatter}, ConverterParameter='\{0:f4\}'}" HorizontalAlignment="Right"  />
                            </DataTemplate>
                    </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Y Coord" Width="65" >
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock 
                                Text="{Binding AbsY, Converter={StaticResource formatter}, ConverterParameter='\{0:f4\}'}" HorizontalAlignment="Right"  />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                    <GridViewColumn Header="Angle"  Width="65">
                        <GridViewColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock 
                                Text="{Binding Angle, Converter={StaticResource formatter}, ConverterParameter='\{0:f2\}'}" HorizontalAlignment="Right"  />
                            </DataTemplate>
                        </GridViewColumn.CellTemplate>
                    </GridViewColumn>
                </GridView>
            </ListView.View>
        </ListView>
        <StackPanel Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="2" >
            <TextBlock Margin="10,0,0,0" Text="Double-Click a row in the grid to toggle hole visibility." />
            <Canvas Margin="10,10,10,10" Name="canvas1" Background="CadetBlue"  Width="500" Height="500" />
        </StackPanel>
        <StackPanel Grid.Row="1" Grid.Column="0">
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="Bolt Cir Dia. " Width="75" />
                <TextBox Name="txtBoltCirDia" Text="{Binding Path=BoltCirDia, ElementName=winBoltCircle}"
                         PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" Height="25" Width="100" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" >
                <TextBlock Text="No. of Holes: " Width="75" />
                <TextBox Name="txtHoleCount" Text="{Binding Path=HoleCount, ElementName=winBoltCircle}"
                         PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" Height="25" Width="100" />
                <Button Name="btnHoleCountDecrease" Click="btnHoleCountDecrease_Click" Margin="5,0,0,0" Width="25">-</Button>
                <Button Name="btnHoleCountIncrease" Click="btnHoleCountIncrease_Click" Margin="5,0,0,0" Width="25">+</Button>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="Start Angle: " Width="75"/>
                <TextBox Name="txtStartAngle" Text="{Binding Path=StartAngle, ElementName=winBoltCircle}" 
                         PreviewGotKeyboardFocus="TextBox_PreviewGotKeyboardFocus" Height="25" Width="100" />
                <Button Name="btnStartAngleDecrease" Click="btnStartAngleDecrease_Click" Margin="5,0,0,0" Width="25">-</Button>
                <Button Name="btnStartAngleIncrease" Click="btnStartAngleIncrease_Click" Margin="5,0,0,0" Width="25">+</Button>
            </StackPanel>
        </StackPanel>
        <StackPanel Grid.Column="2" Grid.Row="1" >
        <Button Name="btnDraw" Height="36" VerticalAlignment="Top" Click="btnDraw_Click">ReDraw</Button>
        <StackPanel Orientation="Horizontal" Grid.Column="2" Grid.Row="1" Margin="0,10,0,0">
           <TextBlock Text="Hole Size" VerticalAlignment="Center" Margin="0,0,10,0"/>
           <Button Name="btnHoleSizeDecrease" Click="btnHoleSizeDecrease_Click" Margin="5,0,0,0" Width="25">-</Button>
           <Button Name="btnHoleSizeIncrease" Click="btnHoleSizeIncrease_Click" Margin="5,0,0,0" Width="25">+</Button>
        </StackPanel>
         </StackPanel>
        
    </Grid>
</Window>
Code behind:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;



namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window, INotifyPropertyChanged
    {

        private int _HoleCount;
        private double _BoltCirDia;
        private double _StartAngle;
        private double _AngularSpacing;


        private ObservableCollection<Hole> HoleList {get; set;}
        
        // Canvas sketch related fields
        public double SketchBoltCirRad;

        public double SketchX0 {get; set; }
        public double SketchY0 { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;
        
        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }


        }
        
        public double BoltCirDia
        {
            get { return _BoltCirDia; }
            set
            {
              _BoltCirDia = value;
              NotifyPropertyChanged("BoltCirDia");
              RepaintScreen();
            }
        }

        public double StartAngle
        {
            get { return _StartAngle; }
            set
            {
                _StartAngle = value;
                NotifyPropertyChanged("StartAngle");
                RepaintScreen();
            }
        }

        public double AngularSpacing
        {
            get { return _AngularSpacing; }
            set { _AngularSpacing = value; }
        }

        public int HoleCount
        {
            get { return _HoleCount; }
            set
            {
                if (value >= 0)
                {
                    _HoleCount = value;
                }
                else
                {
                    _HoleCount = 0;
                }
              if (value > 0)
              {
                  _AngularSpacing = 360.0 / _HoleCount;
              }
              else
              {
                  _AngularSpacing = 0;
              }
              NotifyPropertyChanged("HoleCount");
              RedrawScreen();
            }
        }


        
        //-- Constructor --------------------------------------------
        public Window1()
        {
            InitializeComponent();

            HoleList = new ObservableCollection<Hole>();

            SketchX0 = canvas1.Width / 2;
            SketchY0 = canvas1.Height / 2;                   
            SketchBoltCirRad = canvas1.Width / 2 * .7;

            CoordinateGrid.ItemsSource = HoleList; // Point the ListView to the HoleList collection
            
            //-- Set some default values for the UI
            BoltCirDia = 12.0;
            HoleCount = 6;
            StartAngle = 0;

        }

       public void CreateHoleList()
        {
            HoleList.Clear();

            if (HoleCount>0)
            {
                int x;
                double CurrentAngle = StartAngle;

                for (x = 1; x <= HoleCount; x++)
                {
                    Hole NewHole = new Hole();
                    NewHole.HoleNumber = x;
                    NewHole.HoleEntity.Stroke = Brushes.Black;

                    //-- Set BCR and Angle, and let the Hole calculate the absolute coords of each hole
                    NewHole.BoltCirRad = this.BoltCirDia/2.0;
                    NewHole.Angle = CurrentAngle;

                    //--Setup HoleLabel (position happens in UpdateHoles()---------
                    NewHole.HoleLabel.Text=x.ToString();
                    NewHole.HoleLabel.TextAlignment = TextAlignment.Center;
                    NewHole.HoleLabel.Foreground = Brushes.White;
                    NewHole.HoleLabel.FontSize = 12;

                    HoleList.Add(NewHole);

                    CurrentAngle = StartAngle+x*AngularSpacing; // Increment the angle for the next Hole

                }
            }
        }

       public void DrawGridLines()
        {
            int LineSpacing = 20;
            double LineWidth = 0.5;
            Brush LineColor = Brushes.Gray;

            //-- Horizontal Grid Lines (work from Center to Left, then Center to Right)
            for (double x = 0; x <= canvas1.Width / 2; x += LineSpacing)
            {
                for (int y = -1; y <= 1; y += 2)
                {
                    Line VerticalGraphLine = new Line();
                    VerticalGraphLine.X1 = SketchX0 + x * y;
                    VerticalGraphLine.Y1 = 0;
                    VerticalGraphLine.X2 = VerticalGraphLine.X1;
                    VerticalGraphLine.Y2 = canvas1.Height;
                    VerticalGraphLine.Stroke = LineColor;
                    VerticalGraphLine.StrokeThickness = LineWidth;
                    canvas1.Children.Add(VerticalGraphLine);
                }
            }

            //-- Vertical Grid Lines (work from Center Up, then Center down)
            for (double x = 0; x <= canvas1.Height / 2; x += LineSpacing)
            {
                for (int y = -1; y <= 1; y += 2)
                {
                    Line HorizontalGraphLine = new Line();
                    HorizontalGraphLine.X1 = 0;
                    HorizontalGraphLine.Y1 = SketchY0 + x * y;
                    HorizontalGraphLine.X2 = canvas1.Height;
                    HorizontalGraphLine.Y2 = HorizontalGraphLine.Y1;
                    HorizontalGraphLine.Stroke = LineColor;
                    HorizontalGraphLine.StrokeThickness = LineWidth;
                    canvas1.Children.Add(HorizontalGraphLine);
                }
            }

        }
        
       public void DrawBoltCir()
        {
            Ellipse BoltCirEntity = new Ellipse();
            BoltCirEntity.Width = SketchBoltCirRad * 2;
            BoltCirEntity.Height = SketchBoltCirRad * 2;
            BoltCirEntity.Stroke = Brushes.Black;
            BoltCirEntity.Margin = new Thickness(SketchX0 - SketchBoltCirRad, SketchY0 - SketchBoltCirRad, 0, 0);

            Line HorizontalCL = new Line();
            HorizontalCL.X1 = 10;
            HorizontalCL.Y1 = SketchY0;
            HorizontalCL.X2 = canvas1.Width-10;
            HorizontalCL.Y2 = SketchY0;
            HorizontalCL.Stroke = Brushes.Black;
            HorizontalCL.StrokeThickness = 1;

            Line VerticalCL = new Line();
            VerticalCL.X1 = SketchX0;
            VerticalCL.Y1 = 10;
            VerticalCL.X2 = SketchX0;
            VerticalCL.Y2 = canvas1.Height-10;
            VerticalCL.Stroke = Brushes.Black;
            VerticalCL.StrokeThickness = 1;

            //-- Add objects to Canvas
            canvas1.Children.Add(BoltCirEntity);
            canvas1.Children.Add(HorizontalCL);
            canvas1.Children.Add(VerticalCL);

        }

       public void DrawHoles()
        {
           // This methods adds the HoleEntity and HoleLabel to the canvas
           // The method UpdateHoles() must be used to set the sketch positions for these objects
           // Canvas clearing should be handled outside this method as needed.
           foreach (Hole Hole in HoleList)
            {
                canvas1.Children.Add(Hole.HoleEntity);
                canvas1.Children.Add(Hole.HoleLabel);
            }
        }
        
       private void UpdateHoles()
       {
           foreach (Hole HoleEnt in HoleList)
           {
               //-- Update absolute coord points on the Hole by setting its properties -----
               //-- The Hole object will calculate the absolute X and Y in its poperty setters
               HoleEnt.BoltCirRad = this.BoltCirDia/2;
               HoleEnt.Angle=(HoleEnt.HoleNumber-1)*AngularSpacing+StartAngle;

               //--Update the Hole sketch data for the Canvas layout ----
               HoleEnt.HoleEntity.Width = HoleEnt.HoleDia;
               HoleEnt.HoleEntity.Height = HoleEnt.HoleDia;
               HoleEnt.CanvasX = SketchX0 + SketchBoltCirRad * Math.Cos(dtr(HoleEnt.Angle)) - HoleEnt.HoleDia / 2;
               HoleEnt.CanvasY = SketchY0 - SketchBoltCirRad * Math.Sin(dtr(HoleEnt.Angle)) - HoleEnt.HoleDia / 2;
               HoleEnt.HoleEntity.Margin = new Thickness(HoleEnt.CanvasX, HoleEnt.CanvasY, 0, 0);

               //---Update the HoleLabel sketch coords for the Canvas -----
               double TextCLR = (SketchBoltCirRad - HoleEnt.HoleDia / 2 - HoleEnt.HoleLabel.FontSize);
               double HoleLabelX = (SketchX0+TextCLR * Math.Cos(dtr(HoleEnt.Angle))-HoleEnt.HoleLabel.FontSize/2);
               double HoleLabelY = (SketchY0-TextCLR * Math.Sin(dtr(HoleEnt.Angle))-HoleEnt.HoleLabel.FontSize*.6);
               HoleEnt.HoleLabel.Margin = new Thickness(HoleLabelX, HoleLabelY,0,0);

           }
       }

       public class Hole:INotifyPropertyChanged
        {
            public Ellipse HoleEntity = new Ellipse();
            public TextBlock HoleLabel = new TextBlock();

            public static double _HoleDia = 20;

            public int HoleNumber { get; set; }
            public double CanvasX { get; set; }
            public double CanvasY { get; set; }
            public double HoleLabelX { get; set; }
            public double HoleLabelY { get; set; }
            public string AbsXDisplay{ get; set; }
            public string AbsYDisplay { get; set; }
            private bool _Visible;
            private double _AbsX;
            private double _AbsY;
            private double _Angle;
            private double _BoltCirRad;

            public event PropertyChangedEventHandler PropertyChanged;

            public Hole()
            {
                HoleEntity.Width = _HoleDia;
                HoleEntity.Height = _HoleDia;
                Visible = true;
            }

           private void NotifyPropertyChanged(String info)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(info));
                }
            }

            public bool Visible
            {
                get { return _Visible; }
                set
                {
                    _Visible = value;
                    HoleEntity.Visibility = value ? Visibility.Visible : Visibility.Hidden;
                    NotifyPropertyChanged("Visible");
                }
            }
            
           public double AbsX
            {
                get { return _AbsX; }
                set
                {
                    _AbsX = value;
                    AbsXDisplay = String.Format("{0:f4}", value);
                    NotifyPropertyChanged("AbsX");
                }
            }

            public double AbsY
            {
                get { return _AbsY; }
                set
                {
                    _AbsY = value;
                    AbsYDisplay = String.Format("{0:f4}", value);
                    NotifyPropertyChanged("AbsY");
                }
            }

           public double HoleDia
            {
                get { return _HoleDia;}
                set {
                      _HoleDia = value;
                      NotifyPropertyChanged("HoleDia");
                    }
            }

            public double BoltCirRad
            {
                get{return _BoltCirRad;}
                set
                {
                    _BoltCirRad = value;
                    AbsX = (this.BoltCirRad * Math.Cos(dtr(this.Angle)));
                    AbsY = (this.BoltCirRad * Math.Sin(dtr(this.Angle)));
                }
            }

            public double Angle
            {
                get{return _Angle;}
                set
                {
                    _Angle = value;
                    AbsX = (this.BoltCirRad * Math.Cos(dtr(this.Angle)));
                    AbsY = (this.BoltCirRad * Math.Sin(dtr(this.Angle)));
                    NotifyPropertyChanged("Angle");
                }
            }
        
        }

       public static double dtr(double degrees)
        {
            double radians = (Math.PI / 180) * degrees;
            return (radians);
        }

       private void ChangeHoleCount(int ChangeAmount)
        {
            if(HoleCount+ChangeAmount>=0)
            { 
                HoleCount+=ChangeAmount;
            }

        }

       private void ChangeStartAngle(int ChangeAmount)
        {
            StartAngle+=ChangeAmount;
        }

       private void ChangeHoleSketchSize(int ChangeAmount)
        {
            if (Hole._HoleDia + ChangeAmount > 0)
            {
                Hole._HoleDia += ChangeAmount;
            }
            UpdateHoles();
            //RepaintScreen();
        }

       private void ToggleHoleVisiblity(Hole SelectedHole)
       {
           SelectedHole.Visible = (SelectedHole.Visible) ? false : true;
           RepaintScreen();
       }


        private void RedrawScreen()
        {
            canvas1.Children.Clear();
            CreateHoleList(); // Recreate the Hole list collection, which re-calcs the absolute coordinates and angle of each hole
            DrawGridLines();
            DrawBoltCir();
            DrawHoles();
            UpdateHoles(); // Recalculate the abs and canvas coords on the HoleList. Will update grid and update on the canvas
        }

        private void RepaintScreen()
        {
            UpdateHoles(); // Recalculate the abs and canvas coords on the HoleList so we can draw the holes on the canvas
        }


        private void TextBox_PreviewGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
        {
          ((TextBox)sender).SelectAll();
        }

        private void btnDraw_Click(object sender, RoutedEventArgs e)
        {
            RedrawScreen();
        }

        private void btnHoleCountIncrease_Click(object sender, RoutedEventArgs e)
        {
            ChangeHoleCount(1);
        }

        private void btnHoleCountDecrease_Click(object sender, RoutedEventArgs e)
        {
            ChangeHoleCount(-1);
        }

        private void btnStartAngleIncrease_Click(object sender, RoutedEventArgs e)
        {
            ChangeStartAngle(1);
        }
        private void btnStartAngleDecrease_Click(object sender, RoutedEventArgs e)
        {
            ChangeStartAngle(-1);
        }

        private void btnStartAngleIncrease_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ChangeStartAngle(1);
        }

        private void btnStartAngleDecrease_MouseDown(object sender, MouseButtonEventArgs e)
        {
            ChangeStartAngle(-1);
        }

        private void btnHoleSizeDecrease_Click(object sender, RoutedEventArgs e)
        {
            ChangeHoleSketchSize(-1);
        }

        private void btnHoleSizeIncrease_Click(object sender, RoutedEventArgs e)
        {
            ChangeHoleSketchSize(1);
        }

        private void CoordinateGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            var lvRef=(ListView)sender;
            Hole SelectedHole = (Hole)lvRef.SelectedItem;

            ToggleHoleVisiblity(SelectedHole);
        }




    }
    [ValueConversion(typeof(object), typeof(string))]
    public class FormattingConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string formatString = parameter as string;
            if (formatString != null)
            {
                return string.Format(culture, formatString, value);
            }
            else
            {
                return value.ToString();
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            // we don't intend this to ever be called
            return null;
        }
    }
}
>>MMORPG? (help me out here (sorry, I'm not a gamer, and I guess it is related to that))
>
>Massively multiplayer online role-playing game. If you 've heard of WOW (World of Warcraft) that's an example of a MMORPG. It's a few thousand people playing together at the same time.
>
>I've played computer games for fun since before they had graphics. (Many of the early ones were text only.)
>
>>How old is your son?
>
>27
>
>>I'm 41 BTW.
>
>I got ten years on you I'm 51, or maybe I'm 12 haven't decided yet ;-)
>
>>My wife and her mom are 1 day apart... Feb 4 and Feb 5.
>
>cool.
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform