gpt4 book ai didi

WPF必须掌握的技能之自定义控件——实战:自制上传文件显示进度按钮

转载 作者:我是一只小鸟 更新时间:2023-06-11 22:33:41 28 4
gpt4 key购买 nike

自定义控件在WPF开发中是很常见的,有时候某些控件需要契合业务或者美化统一样式,这时候就需要对控件做出一些改造.

目录
  • 按钮设置圆角
  • 按钮上传文件相关定义
  • 测试代码

话不多说直接看效果 。

默认效果: 上传效果

image
image

按钮设置圆角

因为按钮本身没有 CornerRadius 属性,所以只能重写Button的控件模板.

                        
                          <Style TargetType="Button">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Border CornerRadius="5"
                            Width="{TemplateBinding Width}"
                            Background="{TemplateBinding Background}"
                            BorderThickness="1"
                            Height="{TemplateBinding Height}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

                        
                      

在按钮的模板中加入一个Border即可,但是按钮本身没有 CornerRadius 属性,就没办法使用TemplateBinding ,只能写死在样式,那肯定不行,所以我们就需要拓展一下Button按钮.

1.创建一个类 MyProgressButton 继承Button类,由于是新创建的一个类,所以我们可以直接使用依赖属性来完成这件事,在 MyProgressButton 中定义一个圆角弧度的依赖属性.

                        
                          public CornerRadius CornerRadius
        {
            get { return (CornerRadius)GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }

        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius), typeof(MyProgressButton), new PropertyMetadata(default));

                        
                      

2.创建一个 ProgressButtonStyle.xaml 的资源文件,针对 MyProgressButton 定义一些样式,包括弧度的绑定和鼠标移入移出的阴影效果,让我们的按钮立体起来 。

                        
                          <Style TargetType="local:MyProgressButton">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:MyProgressButton">
                    <Border CornerRadius="{TemplateBinding CornerRadius}"
                            Width="{TemplateBinding Width}"
                            Background="{TemplateBinding Background}"
                            BorderThickness="1"
                            Height="{TemplateBinding Height}">
                        <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="False">
                <Setter Property="Effect">
                    <Setter.Value>
                        <DropShadowEffect Color="#cccccc" Direction="270" ShadowDepth="2" Opacity="1" />
                    </Setter.Value>
                </Setter>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Effect" >
                    <Setter.Value>
                        <DropShadowEffect Color="#bbbbbb" Direction="270" ShadowDepth="2" Opacity="1" />
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

                        
                      

3.最后在主界面将 MyProgressButton 的命名控件加入进来,并且用xaml创建一个 MyProgressButton 按钮,自定义一些属性,并且将 ProgressButtonStyle.xaml 样式加入到App.xaml中 。

                        
                          <Window x:Class="ProgressButton.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        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"
        xmlns:local="clr-namespace:ProgressButton"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <local:MyProgressButton Content="上传文件" 
                                Foreground="#555555"
                                Cursor="Hand"
                                FontSize="14"
                                CornerRadius="5"
                                HorizontalAlignment="Center"
                                VerticalAlignment="Center"
                                Height="40" Width="135" 
                                Background="Salmon"
                                x:Name="upload_btn">
        </local:MyProgressButton>
    </Grid>
</Window>


                        
                      
                        
                          <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/ProgressButton;component/Button/ProgressButtonStyle.xaml"></ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

                        
                      

看看效果

按钮上传文件相关定义

1.定义按钮类型 MyProgressButton 的 文件上传进度,是否上传,以及上传时按钮背景色 三个依赖属性 。

                        
                          /// <summary>
        /// 文件上传进度
        /// </summary>
        public double Progress
        {
            get { return (double)GetValue(ProgressProperty); }
            set { SetValue(ProgressProperty, value); }
        }

        public static readonly DependencyProperty ProgressProperty =
            DependencyProperty.Register(nameof(Progress), typeof(double), typeof(MyProgressButton), new PropertyMetadata(double.NegativeZero, OnProgressChanged));

        /// <summary>
        /// 文件是否上传
        /// </summary>
        public bool IsUploading
        {
            get { return (bool)GetValue(IsUploadingProperty); }
            set { SetValue(IsUploadingProperty, value); }
        }

        public static readonly DependencyProperty IsUploadingProperty =
            DependencyProperty.Register(nameof(IsUploading), typeof(bool), typeof(MyProgressButton), new PropertyMetadata(false, OnIsUploadingChanged));

        /// <summary>
        /// 上传时按钮背景色
        /// </summary>
        public Color UploadingColor
        {
            get { return (Color)GetValue(UploadingColorProperty); }
            set { SetValue(UploadingColorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UploadingColor.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UploadingColorProperty =
            DependencyProperty.Register(nameof(UploadingColor), typeof(Color), typeof(MyProgressButton), new PropertyMetadata(Colors.White));

                        
                      

2.如何实现按钮内部的进度显示?有几种办法,比如使用渐进色修改偏移,或者按钮内部套一个进度条,或者按钮内部放两个不同颜色的块控件,动态修改两者的长度。我们选择第一种.

在Progress属性被修改的时候,我们动态修改下按钮内部渐进色的偏移。为 ProgressProperty 添加值变化的回调.

                        
                          private static void OnProgressChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var btn = d as MyProgressButton;
            var progress = (double)e.NewValue;
            if (progress != double.NegativeZero)
            {
                Brush brush = null;
                if ((brush = btn.Background as LinearGradientBrush) != null) //如果按钮本身是线性渐变色则直接修改偏移
                {
                    GradientStopCollection collections =
                        brush.GetValue(GradientBrush.GradientStopsProperty) as GradientStopCollection;

                    collections[1].Offset = collections[0].Offset = progress / 100;
                }
                else //如果本身不是线性渐变色则将背景色修改为线性渐变色
                {
                    LinearGradientBrush linearGradientBrush = new LinearGradientBrush();
                    //设置一个横向的线
                    linearGradientBrush.StartPoint = new Point(0, 0.5);
                    linearGradientBrush.EndPoint = new Point(1, 0.5);

                    GradientStop gradientStop = new GradientStop(); //右边的颜色,即按钮设置的上传时背景色
                    gradientStop.Color = btn!.UploadingColor;

                    GradientStop gradientStop1 = new GradientStop();//左边的颜色,即按钮原本的颜色
                    gradientStop1.Color = (btn!.Background as SolidColorBrush)!.Color;

                    gradientStop.Offset = gradientStop1.Offset = progress / 100;

                    linearGradientBrush.GradientStops.Add(gradientStop1);
                    linearGradientBrush.GradientStops.Add(gradientStop);
                    btn.Background = linearGradientBrush;
                }
            }
        }

                        
                      

在上传文件的时候,将按钮置为禁用,防止重复点击。写一个 IsUploadingProperty 属性的值变化的回调.

                        
                          private static void OnIsUploadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var btn = d as MyProgressButton;
            if ((bool)e.NewValue)
            {
                btn!.IsEnabled = false;
            }
            else
            {
                btn!.IsEnabled = true;
            }
        }

                        
                      
测试代码
                        
                          Binding binding = new Binding();
            binding.Source = this;
            binding.Path = new PropertyPath("Progress");
            binding.Mode = BindingMode.OneWay;
            upload_btn.SetBinding(MyProgressButton.ProgressProperty, binding);

            Binding binding1 = new Binding();
            binding1.Source = this;
            binding1.Path = new PropertyPath("IsUploading");
            binding1.Mode = BindingMode.OneWay;
            upload_btn.SetBinding(MyProgressButton.IsUploadingProperty, binding1);

                        
                      
                        
                          private async void upload_btn_Click(object sender, RoutedEventArgs e)
        {
            IsUploading = true;
            try
            {
                using (FileStream fread = new FileStream("d://d3dcompiler_47.dll", FileMode.Open, FileAccess.Read))
                using (FileStream fwrite = new FileStream("d://d3dcompiler_47_copy.dll", FileMode.OpenOrCreate, FileAccess.Write))
                {
                    var allLength = new FileInfo("d://d3dcompiler_47.dll").Length;
                    long copyedBytes = 0;
                    while (true)
                    {
                        var buffer = ArrayPool<byte>.Shared.Rent(1024 * 10);
                        try
                        {
                            var len = await fread.ReadAsync(buffer, 0, buffer.Length);
                            if (len > 0)
                            {
                                await fwrite.WriteAsync(buffer[..len]);
                                copyedBytes += len;
                                Progress = copyedBytes * 100 / allLength;
                                await Task.Delay(20);
                            }
                            else
                            {
                                break;
                            }
                        }
                        catch { break; }
                        finally
                        {
                            ArrayPool<byte>.Shared.Return(buffer);
                        }
                    }

                    MessageBox.Show("上传成功");
                };
            }
            finally
            {
                IsUploading = false;
            }
        }

                        
                      

最后此篇关于WPF必须掌握的技能之自定义控件——实战:自制上传文件显示进度按钮的文章就讲到这里了,如果你想了解更多关于WPF必须掌握的技能之自定义控件——实战:自制上传文件显示进度按钮的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com