private Control? UpdateControl()

in src/Avalonia.Diagnostics/Diagnostics/Views/PropertyValueEditorView.cs [53:302]


        private Control? UpdateControl()
        {
            _cleanup.Clear();

            if (Property?.PropertyType is not { } propertyType)
                return null;

            if (propertyType == typeof(bool))
                return CreateControl<CheckBox>(ToggleButton.IsCheckedProperty);

            //TODO: Infinity, NaN not working with NumericUpDown
            if (IsValidNumeric(propertyType))
                return CreateControl<NumericUpDown>(
                    NumericUpDown.ValueProperty,
                    new ValueToDecimalConverter(),
                    init: n =>
                    {
                        n.Increment = 1;
                        n.NumberFormat = new NumberFormatInfo { NumberDecimalDigits = 0 };
                        n.ParsingNumberStyle = NumberStyles.Integer;
                    },
                    readonlyProperty: NumericUpDown.IsReadOnlyProperty);

            if (propertyType == typeof(Color))
            {
                var el = new Ellipse { Width = 12, Height = 12, VerticalAlignment = VerticalAlignment.Center };

                el.Bind(
                        Shape.FillProperty,
                        new Binding(nameof(Property.Value)) { Source = Property, Converter = Color2Brush })
                    .DisposeWith(_cleanup);

                var tbl = new TextBlock { VerticalAlignment = VerticalAlignment.Center };

                tbl.Bind(
                        TextBlock.TextProperty,
                        new Binding(nameof(Property.Value)) { Source = Property })
                    .DisposeWith(_cleanup);

                var sp = new StackPanel
                {
                    Orientation = Orientation.Horizontal,
                    Spacing = 2,
                    Children = { el, tbl },
                    Background = Brushes.Transparent,
                    Cursor = new Cursor(StandardCursorType.Hand),
                    IsEnabled = !Property.IsReadonly
                };

                var cv = new ColorView
                {
                    HexInputAlphaPosition = AlphaComponentPosition.Leading, // Always match XAML
                };

                cv.Bind(
                        ColorView.ColorProperty,
                        new Binding(nameof(Property.Value), BindingMode.TwoWay)
                        {
                            Source = Property,
                            Converter = Color2Brush
                        })
                    .DisposeWith(_cleanup);

                FlyoutBase.SetAttachedFlyout(sp, new Flyout { Content = cv });

                sp.PointerPressed += (_, _) => FlyoutBase.ShowAttachedFlyout(sp);

                return sp;
            }

            if (ImplementsInterface<IBrush>(propertyType))
                return CreateControl<BrushEditor>(BrushEditor.BrushProperty);

            var isImage = ImplementsInterface<IImage>(propertyType);
            var isGeometry = propertyType == typeof(Geometry);

            if (isImage || isGeometry)
            {
                var valueObservable = Property.GetObservable(x => x.Value);
                var tbl = new TextBlock { VerticalAlignment = VerticalAlignment.Center };

                tbl.Bind(TextBlock.TextProperty,
                        valueObservable.Select(
                            value => value switch
                            {
                                IImage img => $"{img.Size.Width} x {img.Size.Height}",
                                Geometry geom => $"{geom.Bounds.Width} x {geom.Bounds.Height}",
                                _ => "(null)"
                            }))
                    .DisposeWith(_cleanup);

                var sp = new StackPanel
                {
                    Background = Brushes.Transparent,
                    Orientation = Orientation.Horizontal,
                    Spacing = 2,
                    Children =
                    {
                        new Path
                        {
                            Data = isImage ? ImageIcon : GeometryIcon,
                            Fill = Brushes.Gray,
                            Width = 12,
                            Height = 12,
                            Stretch = Stretch.Uniform,
                            VerticalAlignment = VerticalAlignment.Center
                        },
                        tbl
                    }
                };

                if (isImage)
                {
                    var previewImage = new Image { Stretch = Stretch.Uniform, Width = 300, Height = 300 };

                    previewImage
                        .Bind(Image.SourceProperty, valueObservable)
                        .DisposeWith(_cleanup);

                    ToolTip.SetTip(sp, previewImage);
                }
                else
                {
                    var previewShape = new Path
                    {
                        Stretch = Stretch.Uniform,
                        Fill = Brushes.White,
                        VerticalAlignment = VerticalAlignment.Center,
                        HorizontalAlignment = HorizontalAlignment.Center
                    };

                    previewShape
                        .Bind(Path.DataProperty, valueObservable)
                        .DisposeWith(_cleanup);

                    ToolTip.SetTip(sp, new Border { Child = previewShape, Width = 300, Height = 300 });
                }

                return sp;
            }

            if (propertyType.IsEnum)
                return CreateControl<ComboBox>(
                    SelectingItemsControl.SelectedItemProperty, init: c =>
                    {
                        c.ItemsSource = Enum.GetValues(propertyType);
                    });

            var tb = CreateControl<CommitTextBox>(
                CommitTextBox.CommittedTextProperty,
                new TextToValueConverter(),
                t =>
                {
                    t.Watermark = "(null)";
                },
                readonlyProperty: TextBox.IsReadOnlyProperty);

            tb.IsReadOnly |= propertyType == typeof(object) ||
                             !StringConversionHelper.CanConvertFromString(propertyType);

            if (!tb.IsReadOnly)
            {
                tb.GetObservable(TextBox.TextProperty).Subscribe(t =>
                {
                    try
                    {
                        if (t != null)
                        {
                            StringConversionHelper.FromString(t, propertyType);
                        }

                        DataValidationErrors.ClearErrors(tb);
                    }
                    catch (Exception ex)
                    {
                        DataValidationErrors.SetError(tb, ex.GetBaseException());
                    }
                }).DisposeWith(_cleanup);
            }

            return tb;

            TControl CreateControl<TControl>(AvaloniaProperty valueProperty,
                    IValueConverter? converter = null,
                    Action<TControl>? init = null,
                    AvaloniaProperty? readonlyProperty = null)
                    where TControl : Control, new()
            {
                var control = new TControl();
                var bindingMode = Property.IsReadonly ? BindingMode.OneWay : BindingMode.TwoWay;

                init?.Invoke(control);

                control.Bind(valueProperty,
                    new Binding(nameof(Property.Value), bindingMode)
                    {
                        Source = Property,
                        Converter = converter ?? new ValueConverter(),
                        ConverterParameter = propertyType
                    }).DisposeWith(_cleanup);

                if (readonlyProperty != null)
                {
                    control[readonlyProperty] = Property.IsReadonly;
                }
                else
                {
                    control.IsEnabled = !Property.IsReadonly;
                }

                return control;
            }

            static bool IsValidNumeric(Type? type)
            {
                if (type == null || type.IsEnum == true)
                {
                    return false;
                }
                var typeCode = Type.GetTypeCode(type);
                if (typeCode == TypeCode.Object)
                {
                    if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
                    {
                        typeCode = Type.GetTypeCode(Nullable.GetUnderlyingType(type));
                    }
                    else
                    {
                        return false;
                    }
                }
                switch (typeCode)
                {
                    case TypeCode.Byte:
                    case TypeCode.Int16:
                    case TypeCode.Int32:
                    case TypeCode.Int64:
                    case TypeCode.SByte:
                    case TypeCode.Single:
                    case TypeCode.UInt16:
                    case TypeCode.UInt32:
                    case TypeCode.UInt64:
                        return true;
                    default:
                        return false;
                }
            }


        }