프로젝트

일반

사용자정보

통계
| 브랜치(Branch): | 개정판:

markus / MarkupToPDF / Controls / Polygon / PolygonControl.cs @ 92c9cab8

이력 | 보기 | 이력해설 | 다운로드 (24 KB)

1
using MarkupToPDF.Common;
2
using MarkupToPDF.Controls.Common;
3
using MarkupToPDF.Serialize.Core;
4
using MarkupToPDF.Serialize.S_Control;
5
using System;
6
using System.Collections.Generic;
7
using System.ComponentModel;
8
using System.Linq;
9
using System.Text;
10
using System.Threading.Tasks;
11
using System.Windows;
12
using System.Windows.Controls;
13
using System.Windows.Media;
14
using System.Windows.Shapes;
15

    
16
namespace MarkupToPDF.Controls.Polygon
17
{
18
     public class PolygonControl : CommentUserInfo, IDisposable, INotifyPropertyChanged, IShapeControl, IMarkupControlData, IPath
19
    {
20
        #region Constructure
21

    
22
        static PolygonControl()
23
        {
24
            DefaultStyleKeyProperty.OverrideMetadata(typeof(PolygonControl), new FrameworkPropertyMetadata(typeof(PolygonControl)));
25
            //ResourceDictionary dictionary = new ResourceDictionary();
26
            //dictionary.Source = new Uri("/MarkupToPDF;component/themes/generic.xaml", UriKind.RelativeOrAbsolute);
27
            //Application.Current.Resources.MergedDictionaries.Add(dictionary);
28
        }
29

    
30
        public PolygonControl()
31
        {
32
            //this.DefaultStyleKey = typeof(PolygonControl);
33
        }
34
        
35
        #endregion
36

    
37
        #region Variable
38
        private const string PART_PolyPath = "PART_PolyPath";
39

    
40
        public Path Base_PolyPath = null;
41

    
42
        #endregion
43

    
44
        #region Internal Method
45
        public override void OnApplyTemplate()
46
        {   
47
            base.OnApplyTemplate();
48

    
49
            Base_PolyPath = GetTemplateChild(PART_PolyPath) as Path;
50

    
51
            if (Base_PolyPath == null)
52
                return;
53

    
54
            this.SetPolyPath();
55
        }
56

    
57

    
58
        #endregion
59

    
60
        #region Method
61

    
62
        public override void ApplyOverViewData()
63
        {
64
            this.OverViewPathData = this.PathData;
65
        }
66

    
67
        #endregion
68

    
69
        #region Dependency Properties
70

    
71
        public static readonly DependencyProperty UserIDProperty = DependencyProperty.Register(
72
                "UserID", typeof(string), typeof(PolygonControl), new PropertyMetadata(null));
73

    
74
        public static readonly DependencyProperty LineSizeProperty = DependencyProperty.Register(
75
              "LineSize", typeof(double), typeof(PolygonControl), new PropertyMetadata((Double)3));
76

    
77
        public static readonly DependencyProperty StrokeColorProperty = DependencyProperty.Register(
78
               "StrokeColor", typeof(SolidColorBrush), typeof(PolygonControl), 
79
               new PropertyMetadata(new SolidColorBrush(Colors.Red)));
80

    
81
        public static readonly DependencyProperty PathDataProperty = DependencyProperty.Register(
82
                "PathData", typeof(Geometry), typeof(PolygonControl), null);
83

    
84
        //강인구 추가
85
        public static readonly DependencyProperty DashSizeProperty = DependencyProperty.Register(
86
                "DashSize", typeof(DoubleCollection), typeof(PolygonControl), new PropertyMetadata(new DoubleCollection { 99999999  }, PointValueChanged));
87

    
88
        public static readonly DependencyProperty OverViewPathDataProperty = DependencyProperty.Register(
89
                "OverViewPathData", typeof(Geometry), typeof(PolygonControl), null);
90
        //강인구 추가
91
        public static readonly DependencyProperty PaintProperty = DependencyProperty.Register(
92
        "Paint", typeof(PaintSet), typeof(PolygonControl), new PropertyMetadata(PaintSet.None, PointValueChanged));
93

    
94
        public static readonly DependencyProperty IsCompletedProperty = DependencyProperty.Register(
95
               "IsCompleted", typeof(bool), typeof(PolygonControl), null);
96

    
97
        public static readonly DependencyProperty StartPointProperty = DependencyProperty.Register(
98
               "StartPoint", typeof(Point), typeof(PolygonControl), new PropertyMetadata(new Point(0, 0), PointValueChanged));
99

    
100
        public static readonly DependencyProperty EndPointProperty = DependencyProperty.Register(
101
               "EndPoint", typeof(Point), typeof(PolygonControl), new PropertyMetadata(new Point(100, 100), PointValueChanged));
102

    
103
        public static readonly DependencyProperty PointSetProperty = DependencyProperty.Register(
104
                "PointSet", typeof(List<Point>), typeof(PolygonControl), new PropertyMetadata(new List<Point>(), PointValueChanged));
105

    
106
        /// <summary>
107
        /// StylusPointSet을 List<Point>로 대체하면 PointValueChanged가 작동안한다.
108
        /// </summary>
109
        //public static readonly DependencyProperty StylusPointSetProperty = DependencyProperty.Register(
110
        //        "PointC", typeof(StylusPointSet), typeof(PolygonControl), new PropertyMetadata(new StylusPointSet(), PointValueChanged));
111

    
112
        public static readonly DependencyProperty AngleProperty =
113
            DependencyProperty.Register("Angle", typeof(double), typeof(PolygonControl), new PropertyMetadata((double)0.0, new PropertyChangedCallback
114
                (AngleValueChanged)));
115

    
116
        public static readonly DependencyProperty CenterXProperty =
117
            DependencyProperty.Register("CenterX", typeof(double), typeof(PolygonControl), new PropertyMetadata((double)0, OnCenterXYChanged));
118

    
119
        public static readonly DependencyProperty CenterYProperty =
120
            DependencyProperty.Register("CenterY", typeof(double), typeof(PolygonControl), new PropertyMetadata((double)0, OnCenterXYChanged));
121

    
122
        public static readonly DependencyProperty IsSelectedProperty =
123
            DependencyProperty.Register("IsSelected", typeof(bool), typeof(PolygonControl), new FrameworkPropertyMetadata(false, IsSelectedChanged));
124

    
125
        public static readonly DependencyProperty ControlTypeProperty =
126
            DependencyProperty.Register("ControlType", typeof(ControlType), typeof(PolygonControl), new FrameworkPropertyMetadata(ControlType.PolygonControl));
127

    
128
        public static readonly DependencyProperty CanvasXProperty = DependencyProperty.Register(
129
                "CanvasX", typeof(double), typeof(PolygonControl), new PropertyMetadata((double)0, OnSetCansvasChanged));
130

    
131
        public static readonly DependencyProperty CanvasYProperty = DependencyProperty.Register(
132
                "CanvasY", typeof(double), typeof(PolygonControl), new PropertyMetadata((double)0, OnSetCansvasChanged));
133

    
134
        #endregion
135

    
136
        #region PropertyChanged Method
137
        public static void OnSetCansvasChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
138
        {
139
            var instance = (PolygonControl)sender;
140

    
141
            if (e.OldValue != e.NewValue && instance != null)
142
            {
143
                instance.SetValue(e.Property, e.NewValue);
144
                //Canvas.SetLeft(instance, instance.CanvasX);
145
                //Canvas.SetTop(instance, instance.CanvasY);
146
            }
147
        }
148

    
149
        public static void PointValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
150
        {
151
            var instance = (PolygonControl)sender;
152

    
153
            if (e.OldValue != e.NewValue && instance != null)
154
            {
155
                instance.SetValue(e.Property, e.NewValue);
156
                //강인구 추가
157
                instance.SetPolyPath();
158
                //instance.SetPolyPath(); 주석처리
159

    
160
            }
161
        }
162
        public static void AngleValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
163
        {
164
            var instance = (PolygonControl)sender;
165

    
166
            if (e.OldValue != e.NewValue && instance != null)
167
            {
168
                instance.SetValue(e.Property, e.NewValue);
169
                instance.SetPolyPath();
170
            }
171
        }
172
        public static void OnCenterXYChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
173
        {
174
            var instance = (PolygonControl)sender;
175
            if (e.OldValue != e.NewValue && instance != null)
176
            {
177
                instance.SetValue(e.Property, e.NewValue);
178
                instance.SetPolyPath();
179
            }
180
        }
181

    
182
        public static void IsSelectedChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
183
        {
184
            //var instance = (PolygonControl)sender;
185

    
186
            //if (e.OldValue != e.NewValue && instance.Base_PolyPath != null)
187
            //{
188
            //    instance.SetValue(e.Property, e.NewValue);
189

    
190
            //    if (instance.IsSelected)
191
            //    {
192
            //        instance.Base_PolyPath.Stroke = new SolidColorBrush(Colors.Blue);
193
            //    }
194
            //    else
195
            //    {
196
            //        instance.Base_PolyPath.Stroke = new SolidColorBrush(Colors.Transparent);
197
            //    }
198
            //}
199
        }
200

    
201
        #endregion
202

    
203
        #region Properties
204

    
205

    
206
        public bool IsCompleted
207
        {
208
            get { return (bool)GetValue(IsCompletedProperty); }
209
            set
210
            {
211
                SetValue(IsCompletedProperty, value);
212
                OnPropertyChanged("IsCompleted");
213
            }
214
        }
215

    
216

    
217
        public Geometry OverViewPathData
218
        {
219
            get { return (Geometry)GetValue(OverViewPathDataProperty); }
220
            set
221
            {
222
                SetValue(OverViewPathDataProperty, value);
223
                OnPropertyChanged("OverViewPathData");
224
            }
225
        }
226

    
227
        public double CanvasX
228
        {
229
            get { return (double)GetValue(CanvasXProperty); }
230
            set
231
            {
232
                if (this.CanvasX != value)
233
                {
234
                    SetValue(CanvasXProperty, value);
235
                    OnPropertyChanged("CanvasX");
236
                }
237
            }
238
        }
239

    
240
        public double CanvasY
241
        {
242
            get { return (double)GetValue(CanvasYProperty); }
243
            set
244
            {
245
                if (this.CanvasY != value)
246
                {
247
                    SetValue(CanvasYProperty, value);
248
                    OnPropertyChanged("CanvasY");
249
                }
250
            }
251
        } 
252

    
253
        public override bool IsSelected
254
        {
255
            get
256
            {
257
                return (bool)GetValue(IsSelectedProperty);
258
            }
259
            set
260
            {
261
                SetValue(IsSelectedProperty, value);
262
                OnPropertyChanged("IsSelected");
263
            }
264
        }
265

    
266
        public PaintSet Paint
267
        {
268
            get { return (PaintSet)GetValue(PaintProperty); }
269
            set
270
            {
271
                if (this.Paint != value)
272
                {
273
                    SetValue(PaintProperty, value);
274
                    OnPropertyChanged("Paint");
275
                }
276
            }
277
        }
278

    
279
        public override ControlType ControlType
280
        {
281
            set
282
            {
283
                SetValue(ControlTypeProperty, value);
284
                OnPropertyChanged("ControlType");
285
            }
286
            get
287
            {
288
                return (ControlType)GetValue(ControlTypeProperty);
289
            }
290
        }
291

    
292
        public Double LineSize
293
        {
294
            get { return (Double)GetValue(LineSizeProperty); }
295
            set
296
            {
297
                if (this.LineSize != value)
298
                {
299
                    SetValue(LineSizeProperty, value);
300
                    OnPropertyChanged("LineSize");
301
                }
302
            }
303
        }
304

    
305
        public DoubleCollection DashSize
306
        {
307
            get { return (DoubleCollection)GetValue(DashSizeProperty); }
308
            set
309
            {
310
                if (this.DashSize != value)
311
                {
312
                    SetValue(DashSizeProperty, value);
313
                    OnPropertyChanged("DashSize");
314
                }
315
            }
316
        }
317
        public string UserID
318
        {
319
            get { return (string)GetValue(UserIDProperty); }
320
            set
321
            {
322
                if (this.UserID != value)
323
                {
324
                    SetValue(UserIDProperty, value);
325
                    OnPropertyChanged("UserID");
326
                }
327
            }
328
        }
329
        public List<Point> PointSet
330
        {
331
            get { return (List<Point>)GetValue(PointSetProperty); }
332
            set { SetValue(PointSetProperty, value);
333
            OnPropertyChanged("PointSet");
334
            }
335
        }        //public StylusPointSet PointC
336
        //{
337
        //    get { return (StylusPointSet)GetValue(StylusPointSetProperty); }
338
        //    set
339
        //    {
340
        //        SetValue(StylusPointSetProperty, value);
341
        //        OnPropertyChanged("PointC");
342
        //    }
343
        //}
344

    
345

    
346
        public double CenterX
347
        {
348
            get { return (double)GetValue(CenterXProperty); }
349
            set { SetValue(CenterXProperty, value);
350
            OnPropertyChanged("CenterX");
351
            }
352
        }
353
        public double CenterY
354
        {
355
            get
356
            {
357
                return (double)GetValue(CenterYProperty);
358
            }
359
            set
360
            {
361
                SetValue(CenterYProperty, value);
362
                OnPropertyChanged("CenterY");
363
            }
364
        }
365
        public override SolidColorBrush StrokeColor
366
        {
367
            get { return (SolidColorBrush)GetValue(StrokeColorProperty); }
368
            set
369
            {
370
                if (this.StrokeColor != value)
371
                {
372
                    SetValue(StrokeColorProperty, value);
373
                    OnPropertyChanged("StrokeColor");
374
                }
375
            }
376
        }
377
        public Geometry PathData
378
        {
379
            get { return (Geometry)GetValue(PathDataProperty); }
380
            set
381
            {
382
                SetValue(PathDataProperty, value);
383
                OnPropertyChanged("PathData");
384
            }
385
        }
386
     
387
        //public double Angle
388
        //{
389
        //    get { return (double)GetValue(AngleProperty); }
390
        //    set
391
        //    {
392
        //        if (this.Angle != value)
393
        //        {
394
        //            SetValue(AngleProperty, value);
395
        //            OnPropertyChanged("Angle");
396
        //        }
397
        //    }
398
        //}
399

    
400
        public Point EndPoint
401
        {
402
            get { return (Point)GetValue(EndPointProperty); }
403
            set
404
            {
405
                SetValue(EndPointProperty, value);
406
                OnPropertyChanged("EndPoint");
407
            }
408
        }
409
        public Point StartPoint
410
        {
411
            get { return (Point)GetValue(StartPointProperty); }
412
            set
413
            {
414
                SetValue(StartPointProperty, value);
415
                OnPropertyChanged("StartPoint");
416
            }
417
        }
418
        #endregion
419

    
420
        public override void UpdateControl()
421
        {
422
            this.StartPoint = new Point(this.PointSet[0].X, this.PointSet[0].Y);
423
            this.EndPoint = new Point(this.PointSet[this.PointSet.Count - 1].X, this.PointSet[this.PointSet.Count - 1].Y);
424

    
425
            SetPolyPath();
426
        }
427

    
428
        private void SetPolyPath()
429
        {
430
            if (Base_PolyPath != null)
431
            {
432
                Base_PolyPath.StrokeDashArray.Clear();
433
                foreach (var item in this.DashSize)
434
                {
435
                    Base_PolyPath.StrokeDashArray.Add(item);
436
                }
437

    
438
                PathGeometry pathGeometry = new PathGeometry();
439
                PathFigure pathFigure = new PathFigure();
440
                PolyLineSegment instance = new PolyLineSegment(this.PointSet, true);
441
               
442
                StartPoint = instance.Points.First();
443
                pathFigure.StartPoint = StartPoint;
444
                EndPoint = instance.Points.Last();
445
                pathFigure.Segments.Add(instance);
446
                pathGeometry.Figures.Add(pathFigure);
447

    
448
                //강인구 추가(Chain이 아닌 Polygon일때만 채우기 및 빗금 하기)
449
                if (ControlType == ControlType.PolygonControl)
450
                {
451
                    switch (this.Paint)
452
                    {
453
                        case PaintSet.None:
454
                            {
455
                                pathFigure.IsFilled = false;
456
                                //강인구 추가
457
                                Base_PolyPath.Fill = null;
458
                            }
459
                            break;
460
                        case PaintSet.Fill:
461
                            {
462
                                Base_PolyPath.Fill = this.StrokeColor;
463
                            }
464
                            break;
465
                        case PaintSet.Hatch:
466
                            {
467
                                var size = this.LineSize > 5 ? 5 : this.LineSize;
468
                                Base_PolyPath.Fill = HatchMake.CreateHatchBrush(this.StrokeColor, 3 * 0.1);
469
                            }
470
                            break;
471
                        default:
472
                            break;
473
                    }
474
                }
475

    
476
                this.PathData = pathGeometry;
477
                this.ApplyOverViewData();
478
            }
479
        }
480

    
481
        public void ChangePaint(PaintSet state)
482
        {
483

    
484
        }
485

    
486
        /// <summary>
487
        /// call when mouse is moving while drawing control
488
        /// </summary>
489
        /// <author>humkyung</author>
490
        /// <param name="pt"></param>
491
        /// <param name="bAxisLocked"></param>
492
        public override void OnCreatingMouseMove(Point pt, bool bAxisLocked)
493
        {
494
            this.PointSet.RemoveAt(this.PointSet.Count - 1);
495

    
496
            Point tmp = pt;
497

    
498
            if (bAxisLocked)
499
            {
500
                CommentAngle = MathSet.returnAngle(this.PointSet[this.PointSet.Count - 1], ref tmp, bAxisLocked);
501
            }
502

    
503
            this.PointSet.Add(tmp);
504

    
505
            this.UpdateControl();
506
        }
507

    
508
        /// <summary>
509
        /// move control point has same location of given pt along given delta
510
        /// </summary>
511
        /// <author>humkyung</author>
512
        /// <date>2019.06.20</date>
513
        /// <param name="pt"></param>
514
        /// <param name="dx"></param>
515
        /// <param name="dy"></param>
516
        public override void OnMoveCtrlPoint(Point pt, double dx, double dy, bool bAxisLocked = false)
517
        {
518
            var pointSet = (this as IPath).PointSet;
519

    
520
            Point selected = MathSet.getNearPoint(pointSet, pt);
521

    
522
            Point NearStartpoint = MathSet.getNearPoint(pointSet, pt);
523

    
524
            var tmpPointSet = pointSet.Select((x,inx)=> new { x,inx});
525

    
526
            var selectPoint = tmpPointSet.Where(x => x.x.Equals(pt));
527

    
528
            if(selectPoint.Count() > 0)
529
            {
530
                if (tmpPointSet.Count() > selectPoint.First().inx + 1)
531
                {
532
                    NearStartpoint = pointSet[selectPoint.First().inx + 1];
533
                }
534
                else
535
                {
536
                    NearStartpoint = pointSet[selectPoint.First().inx - 1];
537
                }
538
            }
539

    
540
            selected.X += dx;
541
            selected.Y += dy;
542

    
543
            Point tmp = selected;
544

    
545
            CommentAngle = MathSet.returnAngle(NearStartpoint, ref tmp, bAxisLocked);
546

    
547
            if (bAxisLocked)
548
            {
549
                selected = tmp;
550
            }
551

    
552
            for (int i = 0; i < (this as IPath).PointSet.Count; i++)
553
            {
554
                if (pt.Equals((this as IPath).PointSet[i]))
555
                {
556
                    (this as IPath).PointSet[i] = selected;
557
                }
558
            }
559
            this.UpdateControl();
560
        }
561

    
562
        /// <summary>
563
        /// return Polygon's area
564
        /// </summary>
565
        /// <author>humkyung</author>
566
        /// <date>2019.06.13</date>
567
        public override Rect ItemRect
568
        {
569
            get
570
            {
571
                double dMinX = double.MaxValue;
572
                double dMinY = double.MaxValue;
573
                double dMaxX = double.MinValue;
574
                double dMaxY = double.MinValue;
575
                foreach (Point pt in this.PointSet)
576
                {
577
                    dMinX = Math.Min(dMinX, pt.X);
578
                    dMinY = Math.Min(dMinY, pt.Y);
579
                    dMaxX = Math.Max(dMaxX, pt.X);
580
                    dMaxY = Math.Max(dMaxY, pt.Y);
581
                }
582

    
583
                return new Rect(new Point(dMinX, dMinY), new Point(dMaxX, dMaxY));
584
            }
585
        }
586

    
587
        /// <summary>
588
        /// Serialize this
589
        /// </summary>
590
        /// <param name="sUserId"></param>
591
        /// <returns></returns>
592
        public override string Serialize()
593
        {
594
            using (S_PolyControl STemp = new S_PolyControl())
595
            {
596
                STemp.TransformPoint = "0|0";
597
                STemp.SizeSet = String.Format("{0}", this.LineSize);
598
                STemp.StrokeColor = this.StrokeColor.Color.ToString();
599
                //STemp.StrokeColor = "#FF000FFF";
600
                STemp.Name = this.GetType().Name.ToString();
601
                //STemp.Toler = this.Toler;
602
                STemp.PaintState = this.Paint;
603
                STemp.Opac = this.Opacity;
604
                STemp.UserID = this.UserID;
605
                STemp.PaintState = this.Paint;
606
                //강인구 추가(Chain인지 Polygon인지 구분)
607
                STemp.Type = this.ControlType;
608
                //STemp.IsTrans = this.isTransOn;
609
                //STemp.IsChain = this.isChain;
610
                STemp.PointSet = new List<Point>();
611
                STemp.DashSize = this.DashSize;
612
                STemp.StartPoint = this.StartPoint;
613
                STemp.EndPoint = this.EndPoint;
614
                STemp.IsCompleted = this.IsCompleted;
615
                foreach (var point in this.PointSet)
616
                {
617
                    STemp.PointSet.Add(point);
618
                }
619
                ///강인구 추가(2017.11.02)
620
                ///Memo 추가
621
                STemp.Memo = this.Memo;
622

    
623
                return "|DZ|" + JsonSerializerHelper.CompressString((STemp.JsonSerialize()));
624
            }
625
        }
626

    
627
        /// <summary>
628
        /// create a polygoncontrol from given string
629
        /// </summary>
630
        /// <param name="str"></param>
631
        /// <returns></returns>
632
        public static PolygonControl FromString(string str, SolidColorBrush brush, string sProjectNo)
633
        {
634
            using (S_PolyControl s = JsonSerializerHelper.JsonDeserialize<S_PolyControl>(str))
635
            {
636
                string[] data2 = s.SizeSet.Split(delimiterChars2, StringSplitOptions.RemoveEmptyEntries);
637
                return new PolygonControl
638
                {
639
                    LineSize = Convert.ToDouble(data2.First()),
640
                    //Toler = s.Toler,
641
                    IsCompleted = s.IsCompleted,
642
                    //PointSet = new List<Point>(),
643
                    Opacity = s.Opac,
644
                    StrokeColor = brush,
645
                    //강인구 추가(Chain인지 Polygon인지 구분)
646
                    ControlType = s.Type,
647
                    DashSize = s.DashSize,
648
                    StartPoint = s.StartPoint,
649
                    EndPoint = s.EndPoint,
650
                    PointSet = s.PointSet,
651
                    UserID = s.UserID,
652
                    Paint = s.PaintState,
653
                    Memo = s.Memo
654
                };
655
            }
656
        }
657

    
658

    
659
        #region Dispose
660
        public void Dispose()
661
        {
662
            //GC.Collect();
663
            ////GC.SuppressFinalize(this);
664
            this.Base_PolyPath = null;
665
        }
666
        #endregion
667

    
668
        #region INotifyPropertyChanged
669
        private void OnPropertyChanged(string name)
670
        {
671
            if (PropertyChanged != null)
672
            {
673
                PropertyChanged(this, new PropertyChangedEventArgs(name));
674
            }
675
        }
676

    
677
        public event PropertyChangedEventHandler PropertyChanged;
678
        #endregion
679
    }
680

    
681
    public class StylusPointSet : INotifyPropertyChanged
682
    {
683
        public StylusPointSet()
684
        {
685
            if (pointSet == null)
686
                pointSet = new List<Point>();
687
        }
688

    
689
        public List<Point> _pointSet;
690

    
691
        public List<Point> pointSet
692
        {
693
            get
694
            {
695
                return _pointSet;
696
            }
697
            set
698
            {
699
                _pointSet = value;
700
                OnPropertyChanged("pointSet");
701
            }
702
        }
703

    
704
        #region INotifyPropertyChanged
705
        private void OnPropertyChanged(string name)
706
        {
707
            if (PropertyChanged != null)
708
            {
709
                PropertyChanged(this, new PropertyChangedEventArgs(name));
710
            }
711
        }
712

    
713
        public event PropertyChangedEventHandler PropertyChanged;
714
        #endregion
715
    }
716
}
클립보드 이미지 추가 (최대 크기: 500 MB)