Avalonia学习(二十九)-仪表

Avalonia制作仪表盘,把控件给大家演示一下,Avalonia有三类自定义控件,分别是用户控件、模版控件、自主控件。前面已经很多用户控件了,这个是演示模版控件,另外一种不知道哪种情况下使用。

前端代码:

<Styles xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:GaugeAvalonia.Views;assembly=GaugeAvalonia"
    x:CompileBindings="False"
  >
  <Design.PreviewWith>
        <Border Padding="20">
            <!-- Add Controls for Previewer Here -->
        </Border>
    </Design.PreviewWith>

  <Style  Selector="local|ArcGauge">
    <Setter Property="Background" Value="#646464"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:ArcGauge}">
          <Border Margin="10">
            <Grid Width="{Binding RelativeSource={RelativeSource Self},Path=Height}">
              <Ellipse Fill="#FF3B3B3B"/>
              <Grid RenderTransformOrigin="0.5,0.5" Margin="2">
                <Grid.RenderTransform>
                  <TransformGroup>
                    <RotateTransform  Angle="{Binding Angle}"/>
                    </TransformGroup>
                </Grid.RenderTransform>
                <Ellipse Width="16" Height="14" Fill="Orange" VerticalAlignment="Top" >
                  <Ellipse.Effect>
                    <BlurEffect Radius="12"/>
                  </Ellipse.Effect>
                </Ellipse>
              </Grid>

              <Grid x:Name="bdGrid" Margin="12" UseLayoutRounding="True" ClipToBounds="True">
                <Ellipse>
                  <Ellipse.Fill>
                    <RadialGradientBrush>
                      <GradientStop Color="#4D000000"/>
                    </RadialGradientBrush>
                  </Ellipse.Fill>
                </Ellipse>
                <Grid>
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition Width="2*"/>
                    <ColumnDefinition/>
                  </Grid.ColumnDefinitions>
                  <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition Height="2*"/>
                    <RowDefinition/>
                  </Grid.RowDefinitions>
                  <Ellipse Stroke="#464646" StrokeThickness="1" Grid.Column="1" Grid.Row="1"/>
                  <Ellipse Stroke="#959595" Margin="4" StrokeThickness="6" Grid.Column="1" Grid.Row="1"/>
                  <Ellipse Stroke="#464646" Margin="14" StrokeThickness="1" Grid.Column="1" Grid.Row="1"/>
                </Grid>
                <Grid>
                  <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                  </Grid.RowDefinitions>
                  <Path  Data="M5,0 5,0 10,120 0,120z" Fill="#0FA9CE" Stretch="Uniform" Margin="0 30 0 0"  HorizontalAlignment="Center">
                    <Path.RenderTransform>
                      <TransformGroup>
                        <RotateTransform    Angle="{Binding Path=Angle, Mode=TwoWay}"/>
                      </TransformGroup>
                    </Path.RenderTransform>
                  </Path>
                </Grid>
                <Ellipse Width="28" Height="28" Fill="Black">
                  <Ellipse.Effect>
                  <!--<DropShadowEffect Color="#0FA9CE" ShadowDepth="0" Direction="0" BlurRadius="16"/>-->
                  </Ellipse.Effect>
                </Ellipse>
                <Border VerticalAlignment="Bottom" BorderBrush="#10ABD1" BorderThickness="2" Margin="0 0 0 12" Background="Black" Padding="8 2" HorizontalAlignment="Center">
                  <TextBlock Text="{Binding Value,RelativeSource={RelativeSource Mode=TemplatedParent}}" FontSize="16" Width="30" TextAlignment="Center" Foreground="White" FontWeight="Bold"/>
                </Border>
              </Grid>
            </Grid>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>

</Styles>

后台代码:

using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Media;
using System.Collections.Generic;
using System.ComponentModel;
using Avalonia.Controls.Templates;
using Avalonia.Controls.Primitives;
using System.Linq;

namespace GaugeAvalonia.Views
{
    public class ArcGauge: TemplatedControl
    {
      
        Grid bdGrid;

        static ArcGauge()
        {
           
           // DefaultStyleKeyProperty.OverrideMetadata(typeof(ArcGauge), new FrameworkPropertyMetadata(typeof(ArcGauge)));
        }
        
        public ArcGauge()
        {
            this.Loaded += ArcGauge_Loaded;
            //Width = 200;
            //Height = 200;
            SetCurrentValue(ValueProperty, 0d);
            SetCurrentValue(MinValueProperty, 0d);
            SetCurrentValue(MaxValueProperty, 100d);
        }

        private void ArcGauge_Loaded(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            InitTick();
        }









        public override void Render(DrawingContext context)
        {
           
            base.Render(context);
          
            bdGrid = (Grid)this.GetTemplateChildren().Where(x => x.Name == "bdGrid").First();
            Refresh();
        

        }
        private void InitTick()
        {
            // 画大刻度
            for (int i = 0; i < 9; i++)
            {
                Line line = new Line();
                line.StartPoint = new Point(0, 0);
                line.EndPoint=new Point(0, 12);
                line.HorizontalAlignment= Avalonia.Layout.HorizontalAlignment
                    .Center;
             
                line.Stroke = Brushes.White;
                line.StrokeThickness = 2;
                line.RenderTransformOrigin = RelativePoint.Center;
              
                line.RenderTransform = new RotateTransform() { Angle = -140 + i * 35 };
                 bdGrid.Children.Add(line);
                DrawText();
            }            // 画小刻度
            for (int i = 0; i < 8; i++)
            {
                var start = -140 + 35 * i + 3.5;
                for (int j = 0; j < 9; j++)
                {
                    Line line = new Line();
                    line.StartPoint = new Point(0, 0);
                    line.EndPoint = new Point(0, 6);
                   
                    line.Stroke = Brushes.White;
                    line.StrokeThickness = 1;
                    line.HorizontalAlignment = Avalonia.Layout.HorizontalAlignment .Center;
                    line.RenderTransformOrigin = RelativePoint.Center;
                    line.RenderTransform = new RotateTransform() { Angle = start + j * 3.5 };
                    bdGrid.Children.Add(line);
                }
            }
        }
        List<TextBlock> textLabels = new List<TextBlock>();
        private void DrawText()
        {
            foreach (var item in textLabels)
            {
                  bdGrid.Children.Remove(item);
            }
            textLabels.Clear();
            var per = MaxValue / 8;
            for (int i = 0; i < 9; i++)
            {
                TextBlock textBlock = new TextBlock();
                textBlock.Text = $"{MinValue + (per * i)}";
                textBlock.HorizontalAlignment =  Avalonia.Layout.HorizontalAlignment.Center;
                textBlock.RenderTransformOrigin = RelativePoint.Center;
                textBlock.RenderTransform = new RotateTransform() { Angle = -140 + i * 35 };
                textBlock.Margin = new Thickness(12);
                textBlock.Foreground = Brushes.White;
                bdGrid.Children.Add(textBlock);
                textLabels.Add(textBlock);
            }
        }


       
        //public static readonly StyledProperty<IBrush> BackgroundProperty =
        //   AvaloniaProperty.Register<ArcGauge, IBrush>(nameof(Value));
        //public IBrush Background
        //{
        //    get
        //    {
        //        return GetValue(BackgroundProperty);
        //    }
        //    set
        //    {
        //        SetValue(BackgroundProperty, value);
        //    }
        //}

        //public static readonly StyledProperty<IBrush> ForegroundProperty =
        // AvaloniaProperty.Register<ArcGauge, IBrush>(nameof(Value));
        //public IBrush Foreground
        //{
        //    get
        //    {
        //        return GetValue(ForegroundProperty);
        //    }
        //    set
        //    {
        //        SetValue(ForegroundProperty, value);
        //    }
       // }



        [Category("值设定")]
        public double Value
        {
            get { return (double)GetValue(ValueProperty); }
            set { SetValue(ValueProperty, value); }
        }
        public static readonly StyledProperty<double> ValueProperty =
            AvaloniaProperty.Register<ArcGauge, double>(nameof(Value), coerce: OnValueChanged);

        private static double OnValueChanged(AvaloniaObject @object, double arg2)
        {
            ArcGauge gauge= @object  as ArcGauge;
            gauge.Refresh();
            return arg2;
        }

        [Category("值设定")]
        public double MinValue
        {
            get { return (double)GetValue(MinValueProperty); }
            set { SetValue(MinValueProperty, value); }
        }
        public static readonly StyledProperty<double> MinValueProperty =
            AvaloniaProperty.Register<ArcGauge, double>(nameof(MinValue), coerce: OnValueChanged);
        public double MaxValue
        {
            get { return (double)GetValue(MaxValueProperty); }
            set { SetValue(MaxValueProperty, value); }
        }
        public static readonly StyledProperty<double> MaxValueProperty =
           AvaloniaProperty.Register<ArcGauge, double>(nameof(MaxValue), coerce: OnValueChanged);


        public double Angle
        {
            get { return (double)GetValue(AngleProperty); }
            set { SetValue(AngleProperty, value); }
        }
        public static readonly StyledProperty<double> AngleProperty =
         AvaloniaProperty.Register<ArcGauge, double>(nameof(Angle));


      
        private void Refresh()
        {

           
            if (Value > MaxValue)
            {
                Angle = 140;

            }
            else if (Value < MinValue)
            {
                Angle = -140;

            }
            else
            {
                var range = MaxValue - MinValue;
                var process = Value / range;
                var tAngle = process * 280 - 140;
                Angle = tAngle;

            }

            
        }
    }
}

运行效果:

目前Avalonia的内容也不知道该演示什么了。估计博文会更新慢了。

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Avalonia是一个**跨平台的UI框架,用于创建桌面应用程序**。 以下是一些关于Avalonia的基本信息和学习资源: 1. **什么是Avalonia?**:Avalonia是一个基于WPF XAML的开源UI框架,它允许开发者使用.NET构建跨平台的桌面应用程序。Avalonia支持多种操作系统,包括Windows、Linux和macOS。 2. **准备工作**:在开始使用Avalonia之前,你需要安装相应的开发环境,并配置项目。这通常包括安装.NET SDK和Avalonia工具包。 3. **创建第一个Avalonia应用程序**:你可以通过官方文档或相关教程来创建你的第一个Avalonia应用,这将帮助你理解基本的应用程序结构和开发流程。 4. **XAML基础**:XAML是一种用于定义用户界面的语言,你可以学习如何使用XAML来创建界面布局和实现数据绑定。 5. **控件和样式**:Avalonia提供了丰富的控件库,你可以学习如何使用这些控件以及如何通过样式和模板来自定义它们的外观。 6. **MVVM模式**:MVVM(Model-View-ViewModel)是一种设计模式,用于分离应用程序的业务逻辑和界面表示。学习MVVM将有助于你构建可维护和可测试的应用程序。 7. **导航和多窗口**:了解如何在Avalonia中进行窗口导航和管理多个窗口,这对于构建复杂的桌面应用程序非常重要。 8. **打包和发布应用程序**:最后,你需要学习如何将你的Avalonia应用程序打包和发布,以便用户可以在他们的计算机上安装和使用你的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值