C#之WPF学习之路(4)

目录

内容控件(1)

Control基类

ContentControl类(内容控件)

ButtonBase基类

ButtonBase概述

ButtonBase 类的常见属性

ButtonBase方法

Button按钮

ToggleButton基类

CheckBox复选框

RadioButton单选框

RepeatButton重复按钮

Label标签


内容控件(1)

Control基类

Control 类作为 WPF 中许多控件的基类,提供了一些基本的属性和方法,但它本身并不负责在界面上显示任何内容。相反,它定义了一个名为 ControlTemplate 的属性,该属性允许派生类(如 Button、TextBox 等)定义自己的外观和行为。

每个控件都可以定义自己的 ControlTemplate,这样在界面上显示时就会根据这个模板来渲染。例如,Button 控件定义了一个按钮样式的模板,TextBox 定义了一个文本框的模板,因此它们在界面上显示的外观和行为是不同的。

这些属性为 Control 基类的子类们提供了各种样式和布局上的控制。以下是这些属性的简要说明:

  • FontStyle:用于设置控件的字体样式,如普通、斜体等。
  • FontStretch:控制字体的伸缩程度,可以使字体更加粗细。
  • FontSize:设置控件的字体大小。
  • FontFamily:定义控件的字体系列,如微软雅黑、Arial 等。
  • Foreground:设置控件的字体颜色,即前景色。
  • Background:控制控件的背景色。
  • BorderThickness:定义控件的边框宽度。
  • IsTabStop:指示控件是否包括在选项卡上的导航窗格中。
  • VerticalContentAlignment:设置控件内容的垂直对齐方式。
  • TabIndex:确定当用户通过使用 TAB 键导航控件时,元素接收焦点的顺序。
  • Padding:控制控件内部内容的填充量。
  • Template:定义控件的模板,用于自定义控件的外观和行为。
  • FontWeight:控制字体的粗细程度。
  • BorderBrush:设置控件的边框背景色。
  • HorizontalContentAlignment:设置控件内容的水平对齐方式。

事件

Control 类提供的两个事件:PreviewMouseDoubleClick 和 MouseDoubleClick。

  • PreviewMouseDoubleClick:表示在鼠标双击或多次单击时触发的事件。PreviewMouseDoubleClick  事件被称为隧道事件或预览事件。它们在事件路由中沿着控件树从外向内传播。
  • MouseDoubleClick:表示在鼠标双击或多次单击时触发的事件。这是一个冒泡事件,它在事件路由中从目标控件开始,沿着控件树从内向外传播至最外层的 Window 窗体。

ContentControl类(内容控件)

ContentControl 在 WPF 中是一个非常有用的类。它的 Content 属性(这个属性的类型是object)可以接收任意引用类型的实例,这使得它非常灵活,可以容纳各种类型的内容,包括 UI 控件、数据、文本等。

ContentControl 最常见的用法是将 UI 控件作为其内容,通过设置 Content 属性来显示这些控件。这使得我们可以在界面中动态地加载和显示不同的控件,从而实现更加灵活和动态的界面设计。

ContentControl 类提供了一些关键的属性和方法,用于管理其内容的呈现和行为。下面是这些属性和方法的简要说明:

  • ContentProperty: 这是一个依赖属性,用于设置 ContentControl 的内容。Content 属性的类型为 object,因此可以接受任意引用类型的实例作为内容。
  • HasContentProperty: 这是一个只读的依赖属性,用于指示 ContentControl 是否包含内容。如果 Content 属性有值,则 HasContent 为 true,否则为 false。
  • ContentTemplateProperty: 这是一个依赖属性,用于设置 ContentControl 内容的数据模板。数据模板定义了内容应该如何呈现在界面上。
  • ContentTemplateSelectorProperty: 这是一个依赖属性,用于设置一个内容模板选择器,根据特定的逻辑动态地选择内容的数据模板。
  • ContentStringFormatProperty: 这是一个依赖属性,用于设置内容的格式化字符串,它指定了如何将内容对象转换为字符串显示在界面上。
  • ContentTemplate: 这是一个属性,用于获取或设置 ContentControl 内容的数据模板。
  • HasContent: 这是一个只读属性,用于指示 ContentControl 是否包含内容。
  • Content: 这是一个属性,用于获取或设置 ContentControl 的内容。
  • ContentStringFormat: 这是一个属性,用于获取或设置内容的格式化字符串。
  • ContentTemplateSelector: 这是一个属性,用于获取或设置内容模板选择器,根据特定的逻辑动态地选择内容的数据模板。
  • LogicalChildren: 这是一个只读属性,用于获取 ContentControl 的逻辑子元素的枚举器。

代码示例

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <Grid>
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <!-- 使用 ContentControl 显示一个文本内容 -->
            <ContentControl Content="Hello, ContentControl!" 
                            HorizontalContentAlignment="Center" 
                            VerticalContentAlignment="Center"
                            Background="LightGray"
                            Padding="10"/>

            <!-- 使用 ContentControl 显示一个按钮 -->
            <ContentControl>
                <Button Content="Click Me!" 
                        HorizontalAlignment="Center" 
                        VerticalAlignment="Center"
                        Padding="10"/>
            </ContentControl>
        </StackPanel>
    </Grid>
</Window>

ButtonBase基类

按钮,几乎每个具有UI界面的软件都会有它的身影,而按钮的形式也是有多种多样的,我们在这里简单的罗列一下。

  • Button(普通按钮):用于触发用户定义的操作或命令。
  • CheckBox(复选框按钮):允许用户从一组选项中选择一个或多个选项。
  • RadioButton(单选框按钮):用于允许用户从一组选项中选择一个选项。
  • ToggleButton(切换按钮):类似于 CheckBox 和 RadioButton,但它可以切换状态。
  • RepeatButton(重复按钮):当用户按住按钮时,它会反复引发 Click 事件。
  • GridViewColumnHeader、DataGridColumnHeader、DataGridRowHeader:用于在数据表格中显示列标题和行标题的按钮。

ButtonBase概述

ButtonBase 是一个抽象类,不能被实例化,但它定义了一些在按钮中非常常见的属性和事件。除了 Click 事件之外,还有一个 Command 属性,用于执行特定的命令。

Command 属性通常与 ICommand 接口一起使用,这是 WPF 中命令模式的一部分。通过将命令与按钮相关联,可以使按钮执行特定的操作,而无需直接处理单击事件。

使用命令模式的好处之一是它支持 MVVM(Model-View-ViewModel)架构模式。在 MVVM 中,按钮只是用户界面的一部分,而处理按钮点击的逻辑则位于视图模型(ViewModel)中。通过将按钮的命令属性绑定到视图模型中的命令对象,可以将用户界面与应用程序逻辑解耦,使代码更易于测试和维护。

ButtonBase 类的常见属性

  • CommandTarget: 获取或设置要执行命令的元素。当命令在 CommandTarget 上执行时,命令处理器将寻找指定的命令以执行相应的操作。
  • CommandParameter: 获取或设置传递给命令的参数。这个参数可以是任意类型的对象,它会随着命令的执行而传递到命令的处理器中。
  • Command: 获取或设置按钮要执行的命令。当按钮被点击时,与此属性关联的命令将被执行。
  • IsPressed: 获取一个值,指示按钮当前是否被按下。这对于自定义按钮样式或动画效果很有用。
  • ClickMode: 获取或设置按钮的单击模式。单击模式定义了按钮何时引发 Click 事件。它可以是 Press(按下时立即引发)或 Release(释放时引发)。
  • IsEnabledCore: 获取一个值,指示按钮是否处于启用状态。这是从 ContentElement 类继承的属性,用于确定按钮是否可以与用户进行交互。

ButtonBase方法

  • OnClick(): 这是一个虚方法,在按钮被点击时调用。在派生类中,您可以重写此方法以定义按钮单击时所触发的特定行为。例如,您可以在重写的 OnClick 方法中执行自定义的逻辑,或者调用基类的 OnClick 方法以确保按钮的默认行为被保留。
  • OnIsPressedChanged(): 这也是一个虚方法,它在按钮的 IsPressed 属性发生变化时调用。在派生类中,您可以重写此方法以在按钮按下或释放时执行特定的操作。这可以用于自定义按钮的外观或动画效果,以便根据按钮的按下状态进行调整。

Button按钮

Button因为继承了ButtonBase,而ButtonBase又继承了ContentControl,因此具有这些类的属性和方法。

下面是Button控件特有的属性的详细说明:

  • IsDefault: 该属性用于指示按钮是否作为默认按钮。当用户按下“Enter”键时,将激活标记为默认的按钮。在对话框中,通常会将主要操作按钮(例如“确定”按钮)设置为默认按钮,以便用户可以通过按下“Enter”键执行该操作。
  • IsCancel: 该属性用于指示按钮是否作为取消按钮。当用户按下“Esc”键时,将激活标记为取消的按钮。通常在对话框中,会将“取消”按钮设置为取消按钮,以便用户可以通过按下“Esc”键关闭对话框或执行取消操作。
  • IsDefaulted: 这是一个只读属性,用于指示按钮是否被激活为默认按钮。如果按钮当前处于活动状态,并且作为默认按钮激活,则此属性将返回true;否则返回false。

通过一个例子来分析Button控件的用法与特点。

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Text="用户名:" Margin="5"/>
        <TextBox x:Name="usernameTextBox" Grid.Row="0" Margin="51,5,482,5"/>

        <TextBlock Text="密码:" Grid.Row="1" Margin="5"/>
        <PasswordBox x:Name="passwordBox" Grid.Row="1" Margin="51,5,0,5" HorizontalAlignment="Left" Width="254"/>

        <Button Grid.Row="2" Content="登录" Margin="51,4,616,1" Click="LoginButton_Click" Grid.RowSpan="2"/>
    </Grid>
</Window>
using System.Windows;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void LoginButton_Click(object sender, RoutedEventArgs e)
        {
            string username = usernameTextBox.Text;
            string password = passwordBox.Password;

            if (username == "admin" && password == "123456")
            {
                MessageBox.Show("登录成功!");
            }
            else
            {
                MessageBox.Show("用户名或密码错误!");
            }
        }
    }
}

注意:x:Name和Name的区别

<TextBox x:Name="usernameTextBox" Grid.Row="0" Margin="51,5,482,5"/>
<PasswordBox x:Name="passwordBox" Grid.Row="1" Margin="51,5,0,5" HorizontalAlignment="Left" Width="254"/>

在WPF中,x:Name 和 Name 两者都可以用来为控件指定名称,但它们的作用域和用法略有不同。

x:Name:

  • x:Name 是 XAML 中的一个属性,用于为控件指定一个名称,使其能够在代码后端( C# )中引用。
  • x:Name 属性值在 XAML 中必须唯一,它不会自动地映射到控件的 Name 属性上。
  • 通常情况下,当你需要在后端代码中引用控件时,使用 x:Name 来为控件命名。

Name:

  • Name 是所有 WPF 控件的公共属性,表示控件的名称。
  • 在 XAML 中,如果没有显式地使用 x:Name 属性来为控件命名,控件也会自动生成一个唯一的名称,这个名称就是控件的 Name 属性值。
  • 在 C# 中,通过代码引用控件时,可以使用控件的 Name 属性,不过这通常是通过 x:Name 隐式赋值的。

综上所述,x:Name 主要用于在 XAML 中为控件指定一个名称,以便在后端代码中引用;而 Name 则是控件的一个公共属性,表示控件的名称,它在 XAML 中可以自动生成,也可以显式地指定。

通过C#代码订阅事件

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Text="用户名:" Margin="5"/>
        <TextBox x:Name="usernameTextBox" Grid.Row="0" Margin="51,5,482,5"/>

        <TextBlock Text="密码:" Grid.Row="1" Margin="5"/>
        <PasswordBox x:Name="passwordBox" Grid.Row="1" Margin="51,5,0,5" HorizontalAlignment="Left" Width="254"/>

        <Button Name="LoginButton" Grid.Row="2" Content="登录" Margin="51,4,616,1" Click="LoginButton_Click" Grid.RowSpan="2"/>
    </Grid>
</Window>
using System;
using System.Windows;
using System.Windows.Controls;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            // 创建事件处理程序并将其附加到按钮的 Click 事件
            LoginButton.Click += LoginButton_Click;
        }

        private void LoginButton_Click(object sender, RoutedEventArgs e)
        {
            string username = usernameTextBox.Text;
            string password = passwordBox.Password;

            if (username == "admin" && password == "123456")
            {
                MessageBox.Show("登录成功!");
            }
            else
            {
                MessageBox.Show("用户名或密码错误!");
            }
        }
    }
}

ToggleButton基类

ToggleButton作为CheckBox和RadioButton的共同基类。这意味着CheckBox和RadioButton都是从ToggleButton类派生出来的,它们共享ToggleButton的。

ToggleButton是一个抽象类,它定义了一些用于创建开关式按钮(如复选框和单选框)的通用属性和方法。具体的开关按钮类型(如CheckBox和`RRadioButton)艾因ToggleButton类,从而实现特定的行为。

通过继承ToggleButton,`ChCheckBox实现了复选框功能,允许用户选择多个选项;而RadioButton则实现了单选框功能,允许用户从多个选项中选择一个。这些控件在UI中的外观和行为可能不同,但它们共享了一些共同的特性,这些特性都来自于它们的基类ToggleButton。

以下是ToggleButton基类提供的两个属性和三个事件的概要:

属性:
IsThreeState:

  • 类型: bool
  • 默认值: false
  • 说明: 指示控件是否支持三种状态(选中、未选中和不确定)。

IsChecked:

  • 类型: bool?
  • 默认值: null
  • 说明: 指示当前控件是否处于选中状态。如果IsThreeState为true,则IsChecked可以为true(选中)、false(未选中)或null(不确定)。

事件:

  • Checked:当控件从未选中状态变为选中状态时引发的事件。
  • Unchecked: 当控件从选中状态变为未选中状态时引发的事件。
  • Indeterminate: 当控件的状态变为不确定状态时引发的事件。

CheckBox复选框

在WPF中,CheckBox控件确实继承自ToggleButton类,而ToggleButton类继承自ButtonBase基类。

这种继承关系使得CheckBox拥有了ToggleButton和ButtonBase提供的属性和事件,从而使得CheckBox能够实现按钮的基本功能,并且具有ToggleButton的状态切换功能,例如支持选中、未选中和不确定状态。

代码示例:

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="你喜欢玩什么?" Margin="5"/>
        <CheckBox Name="_checkbox1" Content="王者荣耀" IsChecked="True"  Margin="5"/>
        <CheckBox Name="_checkbox2" Content="吃鸡" Margin="5"/>
        <CheckBox Name="_checkbox3" Content="英雄联盟" Margin="5"/>
        <Button x:Name="_button" Content="查看一下"  Click="_button_Click"/>
    </StackPanel>
</Window>
using System.Windows;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void _button_Click(object sender, RoutedEventArgs e)
        {
            List<string> selectedGames = new List<string>();

            if (_checkbox1.IsChecked == true)
            {
                selectedGames.Add("王者荣耀");
            }
            if (_checkbox2.IsChecked == true)
            {
                selectedGames.Add("吃鸡");
            }
            if (_checkbox3.IsChecked == true)
            {
                selectedGames.Add("英雄联盟");
            }

            if (selectedGames.Count > 0)
            {
                string games = string.Join(", ", selectedGames);
                MessageBox.Show($"你喜欢玩 {games}!");
            }
            else
            {
                MessageBox.Show("你还没有选择喜欢的游戏!");
            }
        }
    }
}

RadioButton单选框

RadioButton的使用方式与CheckBox类似,但它们的行为不同。RadioButton用于单项选择,一组RadioButton中的每个按钮只能选择一个。

代码示例:

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Text="你最喜欢的编程语言是?" Margin="5"/>
        <RadioButton Name="_radioButton1" Content="C#" Margin="5"/>
        <RadioButton Name="_radioButton2" Content="Java" Margin="5"/>
        <RadioButton Name="_radioButton3" Content="C++" Margin="5"/>
        <Button Name="_button" Content="提交" Click="_button_Click" Margin="5"/>
    </StackPanel>
</Window>
using System.Windows;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void _button_Click(object sender, RoutedEventArgs e)
        {
            if (_radioButton1.IsChecked == true)
            {
                MessageBox.Show("你最喜欢的编程语言是:C#");
            }
            else if (_radioButton2.IsChecked == true)
            {
                MessageBox.Show("你最喜欢的编程语言是:Java");
            }
            else if (_radioButton3.IsChecked == true)
            {
                MessageBox.Show("你最喜欢的编程语言是:Python");
            }
            else
            {
                MessageBox.Show("你还没有选择最喜欢的编程语言!");
            }
        }
    }
}

RepeatButton重复按钮

RepeatButton在按钮被按下后,会首先执行一次Click事件,并且在一定的延迟之后开始不断重复执行Click事件,直到按钮被释放。

RepeatButton 自身提供了两个整型属性,分别是Delay 和Interval 。

  • Delay属性确定了按钮首次重复执行事件之前的延迟时间。
  • Interval属性确定了每次重复执行事件之间的时间间隔。

这样,通过调整这两个属性,可以控制RepeatButton的响应速度和频率。

应用示例

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
        <RepeatButton Content="点击一下" Delay="500" Interval="100" Click="RepeatButton_Click"/>
    </StackPanel>
</Window>
using System.Windows;

namespace WpfApp2
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void RepeatButton_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("点击重复按钮!");
        }
    }
}

Label标签

Label控件用于显示文本标签,并且它的Content属性可以接受任意引用类型的内容,例如字符串、数字、甚至是其他控件等。通过设置Content属性,可以动态地改变Label显示的内容,从而实现一些动态展示或数据绑定的需求。 Label通常用于标识其他控件或显示一些静态文本信息。

例子:

<Window x:Class="WpfApp2.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:WpfApp2"
        mc:Ignorable="d"
        Title="学习之路" Height="450" Width="800">
    <Grid>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <!-- 使用Label显示静态文本 -->
            <Label Content="Hello, World!" FontSize="16" FontWeight="Bold" Margin="0 0 0 20"/>

            <!-- 使用Label显示动态绑定的数据 -->
            <Label Content="{Binding CurrentTime}" FontSize="16"/>
        </StackPanel>
    </Grid>
</Window>
using System;
using System.ComponentModel;
using System.Windows;

namespace WpfApp2
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private string _currentTime;
        public string CurrentTime
        {
            get { return _currentTime; }
            set
            {
                _currentTime = value;
                OnPropertyChanged(nameof(CurrentTime));
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            // 初始化数据源
            CurrentTime = DateTime.Now.ToString("HH:mm:ss");
            // 启动一个定时器,每秒更新一次当前时间
            var timer = new System.Windows.Threading.DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(1);
            timer.Tick += (sender, e) => CurrentTime = DateTime.Now.ToString("HH:mm:ss");
            timer.Start();
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

  • 41
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在奋斗的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值