自定义ColorPicker2类

ColorPicker2.cs代码

using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using System;

namespace AvaloniaUI
{
    [TemplatePart("PART_RedSlider", typeof(Slider))]
    [TemplatePart("PART_GreenSlider", typeof(Slider))]
    [TemplatePart("PART_BlueSlider", typeof(Slider))]
    public class ColorPicker2 : TemplatedControl
    {
        public static readonly StyledProperty<Color> ColorProperty =
            AvaloniaProperty.Register<ColorPicker, Color>(nameof(Color), Colors.Black);

        public static readonly StyledProperty<double> RedProperty =
            AvaloniaProperty.Register<ColorPicker, double>(nameof(Red), 0);

        public static readonly StyledProperty<double> GreenProperty =
            AvaloniaProperty.Register<ColorPicker, double>(nameof(Green), 0);

        public static readonly StyledProperty<double> BlueProperty =
            AvaloniaProperty.Register<ColorPicker, double>(nameof(Blue), 0);

        private Slider? redSlider;
        private Slider? greenSlider;
        private Slider? blueSlider;

        private IDisposable? colorSubscription;
        private IDisposable? redSubscription;
        private IDisposable? greenSubscription;
        private IDisposable? blueSubscription;

        public ColorPicker2()
        {
            // 当 Color 变化 → 更新 RGB
            colorSubscription = this.GetObservable(ColorProperty)
                .Subscribe(OnColorChanged);

            // 当任意 RGB 变化 → 更新 Color
            redSubscription = this.GetObservable(RedProperty)
                .Subscribe(_ => UpdateColorFromRgb());
            greenSubscription = this.GetObservable(GreenProperty)
                .Subscribe(_ => UpdateColorFromRgb());
            blueSubscription = this.GetObservable(BlueProperty)
                .Subscribe(_ => UpdateColorFromRgb());
        }

        public Color Color
        {
            get => GetValue(ColorProperty);
            set => SetValue(ColorProperty, value);
        }

        public double Red
        {
            get => GetValue(RedProperty);
            set => SetValue(RedProperty, value);
        }

        public double Green
        {
            get => GetValue(GreenProperty);
            set => SetValue(GreenProperty, value);
        }

        public double Blue
        {
            get => GetValue(BlueProperty);
            set => SetValue(BlueProperty, value);
        }

        private void OnColorChanged(Color color)
        {
            // 更新 RGB
            Red = (double)color.R;
            Green = (double)color.G;
            Blue = (double)color.B;
        }

        private void UpdateColorFromRgb()
        {
            var newColor = Color.FromRgb((byte)Red, (byte)Green, (byte)Blue);
            if (newColor != Color)
                Color = newColor;
        }

        protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
        {
            base.OnApplyTemplate(e);

            redSlider = e.NameScope.Find<Slider>("PART_RedSlider");
            greenSlider = e.NameScope.Find<Slider>("PART_GreenSlider");
            blueSlider = e.NameScope.Find<Slider>("PART_BlueSlider");

            if (redSlider != null)
                redSlider[!!Slider.ValueProperty] = this[!!RedProperty];

            if (greenSlider != null)
                greenSlider[!!Slider.ValueProperty] = this[!!GreenProperty];

            if (blueSlider != null)
                blueSlider[!!Slider.ValueProperty] = this[!!BlueProperty];
        }

        protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
        {
            base.OnDetachedFromVisualTree(e);

            colorSubscription?.Dispose();
            redSubscription?.Dispose();
            greenSubscription?.Dispose();
            blueSubscription?.Dispose();
        }
    }
}

ColorPicker.axaml代码

<Styles xmlns="https://github.com/avaloniaui"
         xmlns:local="using:AvaloniaUI"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Design.PreviewWith>
  </Design.PreviewWith>

  <!-- Add Styles Here -->
    <Style Selector="local|ColorPicker2">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Padding="{TemplateBinding Padding}">
                        <Grid ColumnDefinitions="*,auto"
                              RowDefinitions="auto,auto,auto"
                              ColumnSpacing="8"
                              RowSpacing="4">
                            <Slider Name="PART_RedSlider"
                                    Minimum="0" Maximum="255"
                                    Foreground="Red"
                                    Background="#22FF0000"
                                    VerticalAlignment="Center">
                                <Slider.Resources>
                                    <SolidColorBrush x:Key="SliderThumbBackground" Color="Red"/>
                                </Slider.Resources>
                            </Slider>

                            <Slider Name="PART_GreenSlider"
                                    Grid.Row="1"
                                    Minimum="0" Maximum="255"
                                    Foreground="LimeGreen"
                                    Background="#2200FF00"
                                    VerticalAlignment="Center">
                                <Slider.Resources>
                                    <SolidColorBrush x:Key="SliderThumbBackground" Color="LimeGreen"/>
                                </Slider.Resources>
                            </Slider>

                            <Slider Name="PART_BlueSlider"
                                    Grid.Row="2"
                                    Minimum="0" Maximum="255"
                                    Foreground="DodgerBlue"
                                    Background="#220000FF"
                                    VerticalAlignment="Center">
                                <Slider.Resources>
                                    <SolidColorBrush x:Key="SliderThumbBackground" Color="DodgerBlue"/>
                                </Slider.Resources>
                            </Slider>

                            <Border Grid.Column="1" Grid.RowSpan="3"
                                    Width="50" Height="50"
                                    BorderBrush="Black"
                                    BorderThickness="1"
                                    CornerRadius="4"
                                    Margin="4,0,0,0">
                                <Border.Background>
                                    <SolidColorBrush Color="{Binding Color, RelativeSource={RelativeSource TemplatedParent}}"/>
                                </Border.Background>
                            </Border>
                        </Grid>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Styles>

ColorPickerUserControlTest.axaml代码

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Width="300" Height="300"
         xmlns:local="using:AvaloniaUI"
        x:Class="AvaloniaUI.ColorPickerUserControlTest"
        Title="ColorPickerUserControlTest">
    <StackPanel>
        <local:ColorPicker2 x:Name="colorPicker"
            Margin="2" Padding="3"
            Color="Beige">
        </local:ColorPicker2>
        <Button x:Name="cmdGet" HorizontalAlignment="Center"
             Margin="5,20,5,0" Padding="2"
             Click="cmdGet_Click">Get Color</Button>

        <Button x:Name="cmdSet" HorizontalAlignment="Center"
                Margin="5,0,5,0" Padding="2"
                Click="cmdSet_Click">Reset Color</Button>

        <Button Margin="5,0,5,0" Padding="2" HorizontalAlignment="Center"
                Click="cmdUndo_Click">Undo</Button>

        <TextBlock x:Name="lblColor" Margin="10" HorizontalAlignment="Center"/>
    </StackPanel>
</Window>

ColorPickerUserControlTest.cs代码

using Avalonia;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using Shares.Avalonia;

namespace AvaloniaUI;

public partial class ColorPickerUserControlTest : Window
{
    private readonly UndoRedoManager undoManager = new();

    public ColorPickerUserControlTest()
    {
        InitializeComponent();
        this.Load("avares://AvaloniaUI/Demos/Book/18/CustomControls/ColorPicker.axaml");//这个是在我的扩展里实现了,以后不再重复这些自定义的函数了。
        undoManager.Attach(colorPicker, ColorPicker2.ColorProperty);//这个是在之前的RedoUndo例子里
    }
    // 点击“Get Color”按钮
    private void cmdGet_Click(object? sender, RoutedEventArgs e)
    {
        if (colorPicker != null)
        {
            var color = colorPicker.Color;
            // Avalonia 中没有 WPF 的 MessageBox,可用自定义对话框或简单显示文本:
            lblColor.Text = $"当前颜色:{color}";
        }
    }

    // 点击“Reset Color”按钮
    private void cmdSet_Click(object? sender, RoutedEventArgs e)
    {
        if (colorPicker != null)
        {
            colorPicker.Color = Colors.Beige;
        }
    }

    // 响应 ColorChanged 事件
    private void colorPicker_ColorChanged(object? sender, ColorChangedEventArgs e)
    {
        if (lblColor != null)
        {
            lblColor.Text = $"颜色变为:{e.NewColor}";
        }
    }
    private void cmdUndo_Click(object? sender, RoutedEventArgs e)
    {
        undoManager.Undo(colorPicker);
    }
}

运行效果

image

 

posted on 2025-11-16 14:37  dalgleish  阅读(0)  评论(0)    收藏  举报