using System; using System.Reflection; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Data; using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Layout; using Avalonia.Markup.Xaml; using Avalonia.Media; using DispenserCommon.Atrributes; using DispenserCommon.Utils; using DispenserHal.Camera.DTO; using DispenserUI.ViewModels.Components; using DispenserUI.ViewModels.DTO; using Masuit.Tools.Reflection; using Control = Avalonia.Controls.Control; using Cursor = Avalonia.Input.Cursor; using HorizontalAlignment = Avalonia.Layout.HorizontalAlignment; using Orientation = Avalonia.Layout.Orientation; using UserControl = Avalonia.Controls.UserControl; namespace DispenserUI.Views.Controls; public partial class CameraParamsEditor : UserControl { public CameraParamsEditor() { DataContext = ViewModel; InitializeComponent(); ViewModel.ReloadCameraParams(); } public CameraParamsVM ViewModel { get; } = ServiceLocator.GetService(); private void InitializeComponent() { AvaloniaXamlLoader.Load(this); CameraParamsPanel = this.Get("CameraParamsPanel"); RenderControls(); } /// /// 根据获取到的参数,渲染参数界面 /// private void RenderControls() { var properties = typeof(CameraParams).GetProperties(); foreach (var property in properties) { var propertyType = property.PropertyType; switch (propertyType.Name) { case nameof(StringValue): CameraParamsPanel.Children.Add(RenderStringParams(property)); break; case nameof(IntValue): CameraParamsPanel.Children.Add(RenderIntParams(property)); break; case nameof(Boolean): CameraParamsPanel.Children.Add(RenderBooleanParams(property)); break; case nameof(FloatValue): CameraParamsPanel.Children.Add(RenderFloatParams(property)); break; case nameof(EnumValue): CameraParamsPanel.Children.Add(RenderEnumParams(property)); break; } } // 刷新页面 InvalidateVisual(); } /// /// 渲染字符串参数 /// /// private Control RenderStringParams(PropertyInfo property) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Height = 50, VerticalAlignment = VerticalAlignment.Center }; var name = new TextBlock { Text = property.GetDescription(), Margin = new Thickness(0, 0, 10, 0), TextWrapping = TextWrapping.Wrap, Width = 80, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }; var value = new TextBlock { Name = property.Name, Width = 250, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }; value.Bind(TextBlock.TextProperty, new Binding(property.Name + ".CurValue")); panel.Children.Add(name); panel.Children.Add(value); return panel; } /// /// 渲染数字参数 /// /// private Control RenderIntParams(PropertyInfo property) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Height = 50, VerticalAlignment = VerticalAlignment.Center }; var name = new TextBlock { Text = property.GetDescription(), Margin = new Thickness(0, 0, 10, 0), Width = 80, TextWrapping = TextWrapping.Wrap, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }; var grid = new Grid { Width = 250, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, ColumnDefinitions = new ColumnDefinitions("*,60") }; var slider = new Slider { Name = property.Name, Background = Brushes.Gray, Cursor = new Cursor(StandardCursorType.Hand), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; slider.Bind(RangeBase.ValueProperty, new Binding(property.Name + ".CurValue") { Mode = BindingMode.TwoWay }); slider.Bind(RangeBase.MinimumProperty, new Binding(property.Name + ".Min") { Mode = BindingMode.TwoWay }); var pro = property.GetCustomAttribute(); if (pro != null && pro.Max != 0) { slider.Maximum = pro.Max; } else { slider.Bind(RangeBase.MaximumProperty, new Binding(property.Name + ".Max") { Mode = BindingMode.TwoWay }); } slider.ValueChanged += OnSliderValueChanged; var value = new NumericUpDown { Name = property.Name, Margin = new Thickness(10, 0, 0, 0), Width = 60, Height = 30, ShowButtonSpinner = false, FormatString = "F0", HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; value.Bind(NumericUpDown.ValueProperty, new Binding(property.Name + ".CurValue") { Mode = BindingMode.TwoWay }); value.ValueChanged += OnNumericValueChanged; grid.Children.Add(slider); grid.Children.Add(value); Grid.SetColumn(slider, 0); Grid.SetColumn(value, 1); panel.Children.Add(name); panel.Children.Add(grid); return panel; } /// /// 渲染bool参数 /// /// private Control RenderBooleanParams(PropertyInfo property) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Height = 50, VerticalAlignment = VerticalAlignment.Center }; var name = new TextBlock { Text = property.GetDescription(), Margin = new Thickness(0, 0, 10, 0), Width = 80, TextWrapping = TextWrapping.Wrap, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }; var value = new ToggleSwitch { Name = property.Name, OnContent = "开启", OffContent = "关闭", Cursor = new Cursor(StandardCursorType.Hand), HorizontalAlignment = HorizontalAlignment.Right, HorizontalContentAlignment = HorizontalAlignment.Center, VerticalContentAlignment = VerticalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; value.Bind(ToggleButton.IsCheckedProperty, new Binding(property.Name) { Mode = BindingMode.TwoWay }); value.IsCheckedChanged += OnToggleSwitchChanged; panel.Children.Add(name); panel.Children.Add(value); return panel; } /// /// 渲染浮点型参数 /// /// private Control RenderFloatParams(PropertyInfo property) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Height = 50, VerticalAlignment = VerticalAlignment.Center }; var name = new TextBlock { Text = property.GetDescription(), Margin = new Thickness(0, 0, 10, 0), Width = 80, TextWrapping = TextWrapping.Wrap, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }; var grid = new Grid { Width = 250, HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, ColumnDefinitions = new ColumnDefinitions("*,60") }; var slider = new Slider { Name = property.Name, Background = Brushes.Gray, Cursor = new Cursor(StandardCursorType.Hand), VerticalAlignment = VerticalAlignment.Center }; slider.Bind(RangeBase.ValueProperty, new Binding(property.Name + ".CurValue") { Mode = BindingMode.TwoWay }); slider.Bind(RangeBase.MinimumProperty, new Binding(property.Name + ".Min") { Mode = BindingMode.TwoWay }); var pro = property.GetCustomAttribute(); if (pro != null && pro.Max != 0) { slider.Maximum = pro.Max; } else { slider.Bind(RangeBase.MaximumProperty, new Binding(property.Name + ".Max") { Mode = BindingMode.TwoWay }); } slider.ValueChanged += OnSliderValueChanged; var value = new NumericUpDown { Name = property.Name, Margin = new Thickness(10, 0, 0, 0), Width = 60, Height = 30, ShowButtonSpinner = false, FormatString = "0.###", HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; value.Bind(NumericUpDown.ValueProperty, new Binding(property.Name + ".CurValue") { Mode = BindingMode.TwoWay }); value.ValueChanged += OnNumericValueChanged; grid.Children.Add(slider); grid.Children.Add(value); Grid.SetColumn(slider, 0); Grid.SetColumn(value, 1); panel.Children.Add(name); panel.Children.Add(grid); return panel; } /// /// 渲染枚举类型参数 /// /// private Control RenderEnumParams(PropertyInfo property) { var panel = new StackPanel { Orientation = Orientation.Horizontal, Height = 50, VerticalAlignment = VerticalAlignment.Center }; var name = new TextBlock { Text = property.GetDescription(), Margin = new Thickness(0, 0, 10, 0), Width = 80, TextWrapping = TextWrapping.Wrap, HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center }; var value = new ComboBox { Name = property.Name, Width = 250, AutoScrollToSelectedItem = true }; value.Bind(ItemsControl.ItemsSourceProperty, new Binding(property.Name + ".Labels") { Mode = BindingMode.TwoWay }); value.Bind(SelectingItemsControl.SelectedIndexProperty, new Binding(property.Name + ".CurIndex") { Mode = BindingMode.TwoWay }); value.SelectionChanged += OnSelectionChanged; panel.Children.Add(name); panel.Children.Add(value); return panel; } /// /// 当选择框发生变化时 /// /// /// private void OnSelectionChanged(object? sender, SelectionChangedEventArgs e) { if (sender is ComboBox { IsDropDownOpen: true } comboBox) { var property = comboBox.Name; var value = comboBox.SelectedIndex; ViewModel.UpdateCameraParams(property, value); } } /// /// 当输入框发生变化时 /// /// /// private void OnNumericValueChanged(object? sender, RoutedEventArgs e) { if (sender is NumericUpDown { IsKeyboardFocusWithin: true } numeric) { var property = numeric.Name; var value = numeric.Value; ViewModel.UpdateCameraParams(property, value); } } /// /// 当滑动条发生变化时 /// /// /// private void OnSliderValueChanged(object? sender, RoutedEventArgs e) { if (sender is Slider { IsFocused: true } slider) { var property = slider.Name; var value = slider.Value; ViewModel.UpdateCameraParams(property, value); } } /// /// 当开关发生变化时 /// /// /// private void OnToggleSwitchChanged(object? sender, RoutedEventArgs e) { if (sender is ToggleButton { IsFocused: true } toggleButton) { var property = toggleButton.Name; var value = toggleButton.IsChecked; ViewModel.UpdateCameraParams(property, value); } } }