Example #1
0
 private static void WriteNeedleElementNode(XElement parent, NeedleElement element)
 {
     parent.Add(new XElement("Needle",
                             new XElement("Location", $"{element.LocationX}, {element.LocationY}"),
                             new XElement("Layer", element.Layer),
                             WriteSubjectNode(element.Subject),
                             new XElement("DaytimeImage", element.DaytimeImage),
                             new XElement("NighttimeImage", element.NighttimeImage),
                             new XElement("TransparentColor", element.TransparentColor),
                             new XElement("DefinedRadius", element.DefinedRadius),
                             new XElement("Radius", element.Radius),
                             new XElement("Color", element.Color),
                             new XElement("DefinedOrigin", element.DefinedOrigin),
                             new XElement("Origin", $"{element.OriginX}, {element.OriginY}"),
                             new XElement("InitialAngle", element.InitialAngle),
                             new XElement("LastAngle", element.LastAngle),
                             new XElement("Minimum", element.Minimum),
                             new XElement("Maximum", element.Maximum),
                             new XElement("DefinedNaturalFreq", element.DefinedNaturalFreq),
                             new XElement("NaturalFreq", element.NaturalFreq),
                             new XElement("DefinedDampingRatio", element.DefinedDampingRatio),
                             new XElement("DampingRatio", element.DampingRatio),
                             new XElement("Backstop", element.Backstop),
                             new XElement("Smoothed", element.Smoothed)
                             ));
 }
Example #2
0
        private static void ParseNeedleElementNode(XElement parent, out PanelElement element)
        {
            double[] location = ((string)parent.Element("Location")).Split(',').Select(double.Parse).ToArray();
            double[] origin   = ((string)parent.Element("Origin")).Split(',').Select(double.Parse).ToArray();

            element = new NeedleElement
            {
                LocationX           = location[0],
                LocationY           = location[1],
                Layer               = (int)parent.Element("Layer"),
                Subject             = ParseSubjectNode(parent.Element("Subject")),
                DaytimeImage        = (string)parent.Element("DaytimeImage"),
                NighttimeImage      = (string)parent.Element("NighttimeImage"),
                TransparentColor    = Color24.ParseHexColor((string)parent.Element("TransparentColor")),
                DefinedRadius       = (bool)parent.Element("DefinedRadius"),
                Radius              = (double)parent.Element("Radius"),
                Color               = Color24.ParseHexColor((string)parent.Element("Color")),
                DefinedOrigin       = (bool)parent.Element("DefinedOrigin"),
                OriginX             = origin[0],
                OriginY             = origin[1],
                InitialAngle        = (double)parent.Element("InitialAngle"),
                LastAngle           = (double)parent.Element("LastAngle"),
                Minimum             = (double)parent.Element("Minimum"),
                Maximum             = (double)parent.Element("Maximum"),
                DefinedNaturalFreq  = (bool)parent.Element("DefinedNaturalFreq"),
                NaturalFreq         = (double)parent.Element("NaturalFreq"),
                DefinedDampingRatio = (bool)parent.Element("DefinedDampingRatio"),
                DampingRatio        = (double)parent.Element("DampingRatio"),
                Backstop            = (bool)parent.Element("Backstop"),
                Smoothed            = (bool)parent.Element("Smoothed")
            };
        }
Example #3
0
        private static void WriteNeedleElementNode(string fileName, XElement parent, NeedleElement element)
        {
            XElement needleNode = new XElement("Needle",
                                               new XElement("Location", $"{element.LocationX}, {element.LocationY}"),
                                               new XElement("Layer", element.Layer),
                                               new XElement("Subject", element.Subject)
                                               );

            if (!string.IsNullOrEmpty(element.DaytimeImage))
            {
                needleNode.Add(new XElement("DaytimeImage", Utilities.MakeRelativePath(fileName, element.DaytimeImage)));
            }

            if (!string.IsNullOrEmpty(element.NighttimeImage))
            {
                needleNode.Add(new XElement("NighttimeImage", Utilities.MakeRelativePath(fileName, element.NighttimeImage)));
            }

            needleNode.Add(
                new XElement("TransparentColor", element.TransparentColor),
                new XElement("Color", element.Color),
                new XElement("InitialAngle", element.InitialAngle.ToDegrees()),
                new XElement("LastAngle", element.LastAngle.ToDegrees()),
                new XElement("Minimum", element.Minimum),
                new XElement("Maximum", element.Maximum),
                new XElement("Backstop", element.Backstop),
                new XElement("Smoothed", element.Smoothed)
                );

            if (element.DefinedRadius)
            {
                needleNode.Add(new XElement("Radius", element.Radius));
            }

            if (element.DefinedOrigin)
            {
                needleNode.Add(new XElement("Origin", $"{element.OriginX}, {element.OriginY}"));
            }

            if (element.DefinedNaturalFreq)
            {
                needleNode.Add(new XElement("NaturalFreq", element.NaturalFreq));
            }

            if (element.DefinedDampingRatio)
            {
                needleNode.Add(new XElement("DampingRatio", element.DampingRatio));
            }

            parent.Add(needleNode);
        }
Example #4
0
        private static void WriteNeedleNode(string fileName, StringBuilder builder, NeedleElement element)
        {
            builder.AppendLine("[Needle]");
            WriteKey(builder, "Subject", element.Subject.ToString());
            WriteKey(builder, "Location", element.LocationX, element.LocationY);

            if (element.DefinedRadius)
            {
                WriteKey(builder, "Radius", element.Radius);
            }

            WriteKey(builder, "DaytimeImage", Utilities.MakeRelativePath(fileName, element.DaytimeImage));
            WriteKey(builder, "NighttimeImage", Utilities.MakeRelativePath(fileName, element.NighttimeImage));
            WriteKey(builder, "Color", element.Color.ToString());
            WriteKey(builder, "TransparentColor", element.TransparentColor.ToString());

            if (element.DefinedOrigin)
            {
                WriteKey(builder, "Origin", element.OriginX, element.OriginY);
            }

            WriteKey(builder, "InitialAngle", element.InitialAngle.ToDegrees());
            WriteKey(builder, "LastAngle", element.LastAngle.ToDegrees());
            WriteKey(builder, "Minimum", element.Minimum);
            WriteKey(builder, "Maximum", element.Maximum);

            if (element.DefinedNaturalFreq)
            {
                WriteKey(builder, "NaturalFreq", element.NaturalFreq);
            }

            if (element.DefinedDampingRatio)
            {
                WriteKey(builder, "DampingRatio", element.DampingRatio);
            }

            WriteKey(builder, "Backstop", element.Backstop.ToString());
            WriteKey(builder, "Smoothed", element.Smoothed.ToString());
            WriteKey(builder, "Layer", element.Layer);
        }
Example #5
0
        internal PanelViewModel(Panel panel)
        {
            CompositeDisposable treeItemDisposable = new CompositeDisposable();
            CompositeDisposable listItemDisposable = new CompositeDisposable();

            This = panel
                   .ObserveProperty(x => x.This)
                   .Do(_ => This?.Value.Dispose())
                   .Select(x => new ThisViewModel(x))
                   .ToReadOnlyReactivePropertySlim()
                   .AddTo(disposable);

            TreeItem = panel
                       .ObserveProperty(x => x.TreeItem)
                       .Do(_ => TreeItem?.Value.Dispose())
                       .Select(x => new TreeViewItemViewModel(x))
                       .ToReactiveProperty()
                       .AddTo(disposable);

            TreeItem.Subscribe(x =>
            {
                treeItemDisposable.Dispose();
                treeItemDisposable = new CompositeDisposable();

                x.PropertyChangedAsObservable()
                .ToReadOnlyReactivePropertySlim(mode: ReactivePropertyMode.None)
                .Subscribe(_ => TreeItem.ForceNotify())
                .AddTo(treeItemDisposable);
            })
            .AddTo(disposable);

            SelectedTreeItem = panel
                               .ToReactivePropertyAsSynchronized(
                x => x.SelectedTreeItem,
                x => TreeItem.Value.SearchViewModel(x),
                x => x?.Model
                )
                               .AddTo(disposable);

            ListColumns = panel.ListColumns
                          .ToReadOnlyReactiveCollection(x => new ListViewColumnHeaderViewModel(x))
                          .AddTo(disposable);

            ListItems = panel.ListItems
                        .ToReadOnlyReactiveCollection(x => new ListViewItemViewModel(x))
                        .AddTo(disposable);

            SelectedListItem = panel
                               .ToReactivePropertyAsSynchronized(
                x => x.SelectedListItem,
                x => ListItems.FirstOrDefault(y => y.Model == x),
                x => x?.Model
                )
                               .AddTo(disposable);

            SelectedTreeItem
            .Subscribe(_ =>
            {
                SelectedListItem.Value = null;
                panel.CreateListColumns();
                panel.CreateListItems();
            })
            .AddTo(disposable);

            SelectedListItem
            .Where(x => x != null)
            .Subscribe(x =>
            {
                listItemDisposable.Dispose();
                listItemDisposable = new CompositeDisposable();

                CompositeDisposable tagDisposable = new CompositeDisposable();

                x.Tag
                .OfType <INotifyPropertyChanged>()
                .Subscribe(y =>
                {
                    tagDisposable.Dispose();
                    tagDisposable = new CompositeDisposable();

                    CompositeDisposable subjectDisposable = new CompositeDisposable();

                    y.PropertyChangedAsObservable()
                    .Subscribe(_ => panel.UpdateListItem(x.Model))
                    .AddTo(tagDisposable);

                    Screen screen = y as Screen;
                    PilotLampElement pilotLamp         = y as PilotLampElement;
                    NeedleElement needle               = y as NeedleElement;
                    DigitalNumberElement digitalNumber = y as DigitalNumberElement;
                    DigitalGaugeElement digitalGauge   = y as DigitalGaugeElement;
                    LinearGaugeElement linearGauge     = y as LinearGaugeElement;

                    screen?.ObserveProperty(z => z.Number)
                    .Select(_ => TreeItem.Value.Children[1].Children.FirstOrDefault(z => z.Tag.Value == screen))
                    .Where(z => z != null)
                    .Subscribe(z => panel.RenameScreenTreeItem(z.Model))
                    .AddTo(tagDisposable);

                    pilotLamp?.ObserveProperty(z => z.Subject)
                    .Subscribe(z =>
                    {
                        subjectDisposable.Dispose();
                        subjectDisposable = new CompositeDisposable();

                        z.PropertyChangedAsObservable()
                        .Subscribe(_ => panel.UpdateListItem(x.Model))
                        .AddTo(subjectDisposable);
                    })
                    .AddTo(tagDisposable);

                    needle?.ObserveProperty(z => z.Subject)
                    .Subscribe(z =>
                    {
                        subjectDisposable.Dispose();
                        subjectDisposable = new CompositeDisposable();

                        z.PropertyChangedAsObservable()
                        .Subscribe(_ => panel.UpdateListItem(x.Model))
                        .AddTo(subjectDisposable);
                    })
                    .AddTo(tagDisposable);

                    digitalNumber?.ObserveProperty(z => z.Subject)
                    .Subscribe(z =>
                    {
                        subjectDisposable.Dispose();
                        subjectDisposable = new CompositeDisposable();

                        z.PropertyChangedAsObservable()
                        .Subscribe(_ => panel.UpdateListItem(x.Model))
                        .AddTo(subjectDisposable);
                    })
                    .AddTo(tagDisposable);

                    digitalGauge?.ObserveProperty(z => z.Subject)
                    .Subscribe(z =>
                    {
                        subjectDisposable.Dispose();
                        subjectDisposable = new CompositeDisposable();

                        z.PropertyChangedAsObservable()
                        .Subscribe(_ => panel.UpdateListItem(x.Model))
                        .AddTo(subjectDisposable);
                    })
                    .AddTo(tagDisposable);

                    linearGauge?.ObserveProperty(z => z.Subject)
                    .Subscribe(z =>
                    {
                        subjectDisposable.Dispose();
                        subjectDisposable = new CompositeDisposable();

                        z.PropertyChangedAsObservable()
                        .Subscribe(_ => panel.UpdateListItem(x.Model))
                        .AddTo(subjectDisposable);
                    })
                    .AddTo(tagDisposable);

                    subjectDisposable.AddTo(tagDisposable);
                })
                .AddTo(listItemDisposable);

                tagDisposable.AddTo(listItemDisposable);
            })
            .AddTo(disposable);

            SelectedScreen = SelectedListItem
                             .Select(x => x?.Tag.Value as Screen)
                             .Do(_ => SelectedScreen?.Value?.Dispose())
                             .Select(x => x != null ? new ScreenViewModel(x, panel.Screens.Where(y => y != x)) : null)
                             .ToReadOnlyReactivePropertySlim()
                             .AddTo(disposable);

            SelectedPilotLamp = SelectedListItem
                                .Select(x => x?.Tag.Value as PilotLampElement)
                                .Do(_ => SelectedPilotLamp?.Value?.Dispose())
                                .Select(x => x != null ? new PilotLampElementViewModel(x) : null)
                                .ToReadOnlyReactivePropertySlim()
                                .AddTo(disposable);

            SelectedNeedle = SelectedListItem
                             .Select(x => x?.Tag.Value as NeedleElement)
                             .Do(_ => SelectedNeedle?.Value?.Dispose())
                             .Select(x => x != null ? new NeedleElementViewModel(x) : null)
                             .ToReadOnlyReactivePropertySlim()
                             .AddTo(disposable);

            SelectedDigitalNumber = SelectedListItem
                                    .Select(x => x?.Tag.Value as DigitalNumberElement)
                                    .Do(_ => SelectedDigitalNumber?.Value?.Dispose())
                                    .Select(x => x != null ? new DigitalNumberElementViewModel(x) : null)
                                    .ToReadOnlyReactivePropertySlim()
                                    .AddTo(disposable);

            SelectedDigitalGauge = SelectedListItem
                                   .Select(x => x?.Tag.Value as DigitalGaugeElement)
                                   .Do(_ => SelectedDigitalGauge?.Value?.Dispose())
                                   .Select(x => x != null ? new DigitalGaugeElementViewModel(x) : null)
                                   .ToReadOnlyReactivePropertySlim()
                                   .AddTo(disposable);

            SelectedLinearGauge = SelectedListItem
                                  .Select(x => x?.Tag.Value as LinearGaugeElement)
                                  .Do(_ => SelectedLinearGauge?.Value?.Dispose())
                                  .Select(x => x != null ? new LinearGaugeElementViewModel(x) : null)
                                  .ToReadOnlyReactivePropertySlim()
                                  .AddTo(disposable);

            SelectedTimetable = SelectedListItem
                                .Select(x => x?.Tag.Value as TimetableElement)
                                .Do(_ => SelectedTimetable?.Value?.Dispose())
                                .Select(x => x != null ? new TimetableElementViewModel(x) : null)
                                .ToReadOnlyReactivePropertySlim()
                                .AddTo(disposable);

            SelectedTouch = SelectedListItem
                            .Select(x => x?.Tag.Value as TouchElement)
                            .Do(_ => SelectedTouch?.Value?.Dispose())
                            .Select(x => x != null ? new TouchElementViewModel(x) : null)
                            .ToReadOnlyReactivePropertySlim()
                            .AddTo(disposable);

            AddScreen = SelectedTreeItem
                        .Select(x => x == TreeItem.Value.Children[1])
                        .ToReactiveCommand()
                        .WithSubscribe(panel.AddScreen)
                        .AddTo(disposable);

            AddPilotLamp = SelectedTreeItem
                           .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[0].Children[0]) ||
                                   x == TreeItem.Value.Children[2].Children[0])
                           .ToReactiveCommand()
                           .WithSubscribe(panel.AddPilotLamp)
                           .AddTo(disposable);

            AddNeedle = SelectedTreeItem
                        .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[0].Children[1]) ||
                                x == TreeItem.Value.Children[2].Children[1])
                        .ToReactiveCommand()
                        .WithSubscribe(panel.AddNeedle)
                        .AddTo(disposable);

            AddDigitalNumber = SelectedTreeItem
                               .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[0].Children[2]) ||
                                       x == TreeItem.Value.Children[2].Children[2])
                               .ToReactiveCommand()
                               .WithSubscribe(panel.AddDigitalNumber)
                               .AddTo(disposable);

            AddDigitalGauge = SelectedTreeItem
                              .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[0].Children[3]) ||
                                      x == TreeItem.Value.Children[2].Children[3])
                              .ToReactiveCommand()
                              .WithSubscribe(panel.AddDigitalGauge)
                              .AddTo(disposable);

            AddLinearGauge = SelectedTreeItem
                             .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[0].Children[4]) ||
                                     x == TreeItem.Value.Children[2].Children[4])
                             .ToReactiveCommand()
                             .WithSubscribe(panel.AddLinearGauge)
                             .AddTo(disposable);

            AddTimetable = SelectedTreeItem
                           .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[0].Children[5]) ||
                                   x == TreeItem.Value.Children[2].Children[5])
                           .ToReactiveCommand()
                           .WithSubscribe(panel.AddTimetable)
                           .AddTo(disposable);

            AddTouch = SelectedTreeItem
                       .Select(x => TreeItem.Value.Children[1].Children.Any(y => x == y.Children[1]))
                       .ToReactiveCommand()
                       .WithSubscribe(panel.AddTouch)
                       .AddTo(disposable);

            CopyScreen = SelectedScreen
                         .Select(x => x != null)
                         .ToReactiveCommand()
                         .WithSubscribe(panel.CopyScreen)
                         .AddTo(disposable);

            CopyPilotLamp = SelectedPilotLamp
                            .Select(x => x != null)
                            .ToReactiveCommand()
                            .WithSubscribe(panel.CopyPilotLamp)
                            .AddTo(disposable);

            CopyNeedle = SelectedNeedle
                         .Select(x => x != null)
                         .ToReactiveCommand()
                         .WithSubscribe(panel.CopyNeedle)
                         .AddTo(disposable);

            CopyDigitalNumber = SelectedDigitalNumber
                                .Select(x => x != null)
                                .ToReactiveCommand()
                                .WithSubscribe(panel.CopyDigitalNumber)
                                .AddTo(disposable);

            CopyDigitalGauge = SelectedDigitalGauge
                               .Select(x => x != null)
                               .ToReactiveCommand()
                               .WithSubscribe(panel.CopyDigitalGauge)
                               .AddTo(disposable);

            CopyLinearGauge = SelectedLinearGauge
                              .Select(x => x != null)
                              .ToReactiveCommand()
                              .WithSubscribe(panel.CopyLinearGauge)
                              .AddTo(disposable);

            CopyTimetable = SelectedTimetable
                            .Select(x => x != null)
                            .ToReactiveCommand()
                            .WithSubscribe(panel.CopyTimetable)
                            .AddTo(disposable);

            CopyTouch = SelectedTouch
                        .Select(x => x != null)
                        .ToReactiveCommand()
                        .WithSubscribe(panel.CopyTouch)
                        .AddTo(disposable);

            RemoveScreen = SelectedScreen
                           .Select(x => x != null)
                           .ToReactiveCommand()
                           .WithSubscribe(panel.RemoveScreen)
                           .AddTo(disposable);

            RemovePilotLamp = SelectedPilotLamp
                              .Select(x => x != null)
                              .ToReactiveCommand()
                              .WithSubscribe(panel.RemovePilotLamp)
                              .AddTo(disposable);

            RemoveNeedle = SelectedNeedle
                           .Select(x => x != null)
                           .ToReactiveCommand()
                           .WithSubscribe(panel.RemoveNeedle)
                           .AddTo(disposable);

            RemoveDigitalNumber = SelectedDigitalNumber
                                  .Select(x => x != null)
                                  .ToReactiveCommand()
                                  .WithSubscribe(panel.RemoveDigitalNumber)
                                  .AddTo(disposable);

            RemoveDigitalGauge = SelectedDigitalGauge
                                 .Select(x => x != null)
                                 .ToReactiveCommand()
                                 .WithSubscribe(panel.RemoveDigitalGauge)
                                 .AddTo(disposable);

            RemoveLinearGauge = SelectedLinearGauge
                                .Select(x => x != null)
                                .ToReactiveCommand()
                                .WithSubscribe(panel.RemoveLinearGauge)
                                .AddTo(disposable);

            RemoveTimetable = SelectedTimetable
                              .Select(x => x != null)
                              .ToReactiveCommand()
                              .WithSubscribe(panel.RemoveTimetable)
                              .AddTo(disposable);

            RemoveTouch = SelectedTouch
                          .Select(x => x != null)
                          .ToReactiveCommand()
                          .WithSubscribe(panel.RemoveTouch)
                          .AddTo(disposable);

            treeItemDisposable.AddTo(disposable);
            listItemDisposable.AddTo(disposable);
        }
        internal NeedleElementViewModel(NeedleElement needle) : base(needle)
        {
            CultureInfo culture = CultureInfo.InvariantCulture;

            Subject = needle
                      .ObserveProperty(x => x.Subject)
                      .Do(_ => Subject?.Value.Dispose())
                      .Select(x => new SubjectViewModel(x))
                      .ToReadOnlyReactivePropertySlim()
                      .AddTo(disposable);

            DaytimeImage = needle
                           .ToReactivePropertyAsSynchronized(x => x.DaytimeImage)
                           .AddTo(disposable);

            NighttimeImage = needle
                             .ToReactivePropertyAsSynchronized(x => x.NighttimeImage)
                             .AddTo(disposable);

            TransparentColor = needle
                               .ToReactivePropertyAsSynchronized(
                x => x.TransparentColor,
                x => x.ToString(),
                Color24.ParseHexColor,
                ignoreValidationErrorValue: true
                )
                               .SetValidateNotifyError(x =>
            {
                Color24 result;
                string message;

                Utilities.TryParse(x, out result, out message);

                return(message);
            })
                               .AddTo(disposable);

            DefinedRadius = needle
                            .ToReactivePropertyAsSynchronized(x => x.DefinedRadius)
                            .AddTo(disposable);

            Radius = needle
                     .ToReactivePropertyAsSynchronized(
                x => x.Radius,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                     .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.NonZero, out result, out message);

                return(message);
            })
                     .AddTo(disposable);

            Color = needle
                    .ToReactivePropertyAsSynchronized(
                x => x.Color,
                x => x.ToString(),
                Color24.ParseHexColor,
                ignoreValidationErrorValue: true
                )
                    .SetValidateNotifyError(x =>
            {
                Color24 result;
                string message;

                Utilities.TryParse(x, out result, out message);

                return(message);
            })
                    .AddTo(disposable);

            DefinedOrigin = needle
                            .ToReactivePropertyAsSynchronized(x => x.DefinedOrigin)
                            .AddTo(disposable);

            OriginX = needle
                      .ToReactivePropertyAsSynchronized(
                x => x.OriginX,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                      .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.Any, out result, out message);

                return(message);
            })
                      .AddTo(disposable);

            OriginY = needle
                      .ToReactivePropertyAsSynchronized(
                x => x.OriginY,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                      .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.Any, out result, out message);

                return(message);
            })
                      .AddTo(disposable);

            InitialAngle = needle
                           .ToReactivePropertyAsSynchronized(
                x => x.InitialAngle,
                x => x.ToDegrees().ToString(culture),
                x => double.Parse(x).ToRadians(),
                ignoreValidationErrorValue: true
                )
                           .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.Any, out result, out message);

                return(message);
            })
                           .AddTo(disposable);

            LastAngle = needle
                        .ToReactivePropertyAsSynchronized(
                x => x.LastAngle,
                x => x.ToDegrees().ToString(culture),
                x => double.Parse(x).ToRadians(),
                ignoreValidationErrorValue: true
                )
                        .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.Any, out result, out message);

                return(message);
            })
                        .AddTo(disposable);

            Minimum = needle
                      .ToReactivePropertyAsSynchronized(
                x => x.Minimum,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                      .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.Any, out result, out message);

                return(message);
            })
                      .AddTo(disposable);

            Maximum = needle
                      .ToReactivePropertyAsSynchronized(
                x => x.Maximum,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                      .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.Any, out result, out message);

                return(message);
            })
                      .AddTo(disposable);

            DefinedNaturalFreq = needle
                                 .ToReactivePropertyAsSynchronized(x => x.DefinedNaturalFreq)
                                 .AddTo(disposable);

            NaturalFreq = needle
                          .ToReactivePropertyAsSynchronized(
                x => x.NaturalFreq,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                          .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);

                return(message);
            })
                          .AddTo(disposable);

            DefinedDampingRatio = needle
                                  .ToReactivePropertyAsSynchronized(x => x.DefinedDampingRatio)
                                  .AddTo(disposable);

            DampingRatio = needle
                           .ToReactivePropertyAsSynchronized(
                x => x.DampingRatio,
                x => x.ToString(culture),
                x => double.Parse(x, NumberStyles.Float, culture),
                ignoreValidationErrorValue: true
                )
                           .SetValidateNotifyError(x =>
            {
                double result;
                string message;

                Utilities.TryParse(x, NumberRange.NonNegative, out result, out message);

                return(message);
            })
                           .AddTo(disposable);

            Backstop = needle
                       .ToReactivePropertyAsSynchronized(x => x.Backstop)
                       .AddTo(disposable);

            Smoothed = needle
                       .ToReactivePropertyAsSynchronized(x => x.Smoothed)
                       .AddTo(disposable);
        }