`
schy_hqh
  • 浏览: 558088 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

(八)自定义组件

 
阅读更多
1.组件的作用及其对开发的好处
2.Flex类的层次
3.可见和不可见组件
4.实例化及使用自定义组件
5.自定义组件中创建属性和方法

----------------------------------------------
利用组件将应用程序分割成多个文件,把应用程序分成模块,单独开发与维护都很方便,
还可以成为容易重用的程序功能套件

组件的层次结构
UIComponent
  |-GroupBase
     |-Group
        |-VGroup 、HGroup、 DataRenderer
     -DataGroup
  |-SkinableComponent
     |-ButtonBase
         |-Button
         |ToggleButtonBase
            |-CheckBox
            |-RaddioButton
            |-ToggleButton
     |-SkinnableContainerBase
            |-SkinnableContainer
            |-SkinnableDataContainer
|-ListBase
    |-List
    |-ButtonBarBase
|-ButtonBar
|-ToggleButtonBar
            |-SkinnableTextBase
|-TextInput
|-TextArea
UIComponent继承了一组功能类,用于支持事件分发、交互和包含其它对象等
Object
  EventDispatcher
    DisplayObject
      InteractiveObject
         DisplayObjectContainer
           Sprite
             UIComponent
               All Component

创建自定义组件
1.为预定义的组件添加功能
2.将多个组件组合起来形成一个新的组件
如果是容器,则可以把几个组件的功能放到一起
如果不是容器,那么可以扩展预定义组件的功能,或者扩展现有自定义组件的功能
步骤:
1.创建一个新的文件
2.文件第1行声明XML文档类型定义
3.组件的根标签,设置好命名空间 fx,s,mx
4.组件中添加所需功能,根据需要实现的功能选择标签
5.在将会实例化这个组件的文件中,添加XML命名空间,以便访问此组件
  xmlns:views="views.*" //将views目录下的所有自定义组件包含进来
6.实例化组件
  <views:UserForm/>

组件是应用程序中一个独立运转的部件,接收什么数据,返回什么数据,都需要明确定义

构建组件增强应用程序的架构和功能
如:
显示杂货店商品类别的视图
显示购物车中商品的视图
显示特定商品详情的视图
显示特定类别中所有商品的视图
每个视图都需要一些逻辑以实现与用户的交互
MVC架构中,这些视图的代码通常位于不同的类或多个类中
数据--呈现--逻辑 3者相互分离,尽量做到低耦合
-------------------------------------------------------------------
杂货商品购物应用程序拆分组件:
1.值对象:
        商品(具体商品)Product--->
商品类(各类商品)ShoppingCartItem--->
购物车(包含各个商品分类)ShoppingCart
2.主程序
3.控制条  controlBar组件
4.(组件一)HTTPService远程获取数据
5.(组件二)具体商品及其详细说明(expanded状态)
6.(组件三)购物车中已购物品的列表
以下为源码:
主应用程序FlexGrocery.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   creationComplete="handleCreationComplete(event)" xmlns:views="views.*" xmlns:services="services.*">

	<fx:Declarations>
		<!-- Place non-visual elements (e.g., services, value objects) here -->
		<!-- 将HTTPService获取数据的功能放到两个ActionScript类中进行处理,此处引入即可 -->
		<!-- 提供商品类别服务的组件(不可见组件)-->
		<services:CategoryService id="categoryService"/>
		<!-- 提供具体各种商品服务的组件(不可见组件)-->
		<services:ProductService id="productService"/>
	</fx:Declarations>

	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			//当系统组件构建完成后,会调用到此方法,在这里向远端发起请求,获取数据
			//当数据获取成功后,事件监听器会调用指定的方法处理数据
			private function handleCreationComplete(event:FlexEvent):void {
				categoryService.send();
				productService.send();
			}
			
			//查看当前购物车中的商品
			private function handleViewCartClick( event:MouseEvent ):void {
				bodyGroup.currentState="cartView";//切换到bodyGroup下的cartView状态
			}
		]]>
	</fx:Script>
	
	<!-- 控制条布局 -->
	<s:controlBarLayout>
		<s:BasicLayout/>
	</s:controlBarLayout>
	
	<!-- 控制条 -->
	<s:controlBarContent>
		<s:Button y="10" label="Checkout" id="btnCheckout" right="10"/>
		<s:Button y="10" label="View Cart" id="btnCartView" right="90" click="handleViewCartClick( event )"/>
		<s:Button label="Flex Grocer" x="5" y="5"/>
		<!-- 从categoryService中获取商品种类信息 -->
		<s:List left="200" height="40" dataProvider="{categoryService.categories}" labelField="name">
			<s:layout>
				<s:HorizontalLayout/>
			</s:layout>
		</s:List>
	</s:controlBarContent>
	
	<!-- 实例化商品组件(该组件被单独抽取出来,在主应用程序中实例化) -->
	<!-- 从productService中获取商品 -->
	<views:ShoppingView id="bodyGroup" width="100%" height="100%" groceryInventory="{productService.products}"/>	
	
	<!-- 版权说明 -->
	<s:Label text="(c) 2009, FlexGrocer" right="10" bottom="10"/>
</s:Application>

 

HTTPService组件一
package services
{
	import mx.collections.XMLListCollection;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.mxml.HTTPService;

	/**
	 * 该类提供有关HTTPService的相关功能
	 * 对外提供方法和属性以便调用 
	 * @author lenovo
	 * 
	 */	
	public class CategoryService extends HTTPService
	{
		[Bindable]
		public var categories:XMLListCollection;
		
		
		public function CategoryService(rootURL:String=null, destination:String=null)
		{
			super(rootURL, destination);
			this.resultFormat = "e4x";
			this.url = "http://www.flexgrocer.com/category.xml";
			this.addEventListener(ResultEvent.RESULT,handleCategoryResult);
		}
		
		private function handleCategoryResult(event:ResultEvent):void{
			categories = new XMLListCollection( event.result.category );//将各种商品种类放入XMLListCollection中
		}
	}
}

HTTPService组件二
package services
{
	import mx.collections.ArrayCollection;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.http.mxml.HTTPService;
	
	import valueObjects.Product;
	/**
	 * 该类用于获取所有的商品
	 * 对外提供products(products为ArrayCollection,存放着所有商品) 
	 * @author lenovo
	 * 
	 */	
	public class ProductService extends HTTPService
	{
		[Bindable]
		public var products:ArrayCollection;//获取远程数据,使用e4x找出product节点,转换为对象,放入Array,最后将Array放入ArrayCollection
		
		
		public function ProductService(rootURL:String=null, destination:String=null)
		{
			super(rootURL, destination);
			this.resultFormat = "e4x";//指定返回xml格式的数据以便使用e4x表达式对xml进行操作
			this.url = "http://www.flexgrocer.com/categorizedProducts.xml";//数据源
			this.addEventListener(ResultEvent.RESULT,handleProductResult);//事件监听器,并指定事件处理函数
		}
		
		private function handleProductResult( event:ResultEvent ):void {
			var productArray:Array = new Array();
			var resultData:XMLList = event.result..product;//e4x筛选子节点
			for each (var p:XML in resultData) {			
				var product:Product = Product.buildProductFromAttributes( p );//将每个子节点创建对应的product对象
				productArray.push( product );//添加到数组中
			}
			products = new ArrayCollection( productArray );//将整个数组放入ArrayCollection中,为数组提供代理
		}
	}
}

组件ShoppingView.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx" width="0" height="0" xmlns:components="components.*">
	<s:layout>
		<s:HorizontalLayout/>
	</s:layout>
	<s:states>
		<s:State name="State1"/>
		<s:State name="cartView"/>
	</s:states>
	

	<fx:Script>
		<![CDATA[
			import cart.ShoppingCart;
			import cart.ShoppingCartItem;
			
			import mx.collections.ArrayCollection;
			
			import valueObjects.Product;
			[Bindable]
			public var shoppingCart:ShoppingCart = new ShoppingCart();//创建一个购物车,分别传入不同的商品对象中,而不是在每种商品中都new一个购物车!
			[Bindable]
			public var groceryInventory:ArrayCollection;//用于存放HTTPService返回的各种商品信息
			

			
			//查看当前购物车中的商品
			private function handleViewCartClick( event:MouseEvent ):void {
				this.currentState="cartView";
			}
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
	</fx:Declarations>
	
	<!-- 必须为组件指定在界面中占据的空间大小 否则不可见-->
	<s:VGroup width="100%" height="100%" width.cartView="0" height.cartView="0" visible.cartView="false">
		<!-- 这里没有使用DataGroup对数据进行展现,只是通过硬编码指定了一个商品 -->
		<components:ProductItem id="product1" 
								width="100%" height="100%"
								shoppingCart="{shoppingCart}"
								product="{groceryInventory.getItemAt(0) as Product}"/>
	</s:VGroup>
	
	<!-- 购物车组件 -->
	<s:VGroup height="100%" id="cartGroup" width.cartView="100%">
		<s:List id="cartList"
				dataProvider="{shoppingCart.items}" includeIn="State1"/>			
		<s:Label text="Your Cart Total: $"/>
		<s:Button label="View Cart" click="handleViewCartClick( event )" includeIn="State1"/>
		<mx:DataGrid includeIn="cartView" id="dgCart" width="100%">
			<mx:columns>
				<mx:DataGridColumn headerText="Column 1" dataField="col1"/>
				<mx:DataGridColumn headerText="Column 2" dataField="col2"/>
				<mx:DataGridColumn headerText="Column 3" dataField="col3"/>
			</mx:columns>
		</mx:DataGrid>
		<s:Button includeIn="cartView" label="Continue Shopping" click="this.currentState=''"/>
	</s:VGroup>
</s:Group>



组件ProductItem.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Group xmlns:fx="http://ns.adobe.com/mxml/2009" 
		 xmlns:s="library://ns.adobe.com/flex/spark" 
		 xmlns:mx="library://ns.adobe.com/flex/mx" width="0" height="0">
	<s:layout>
		<s:HorizontalLayout/>
	</s:layout>

	<s:states>
		<s:State name="State1"/>
		<s:State name="expanded"/>
	</s:states>
	
	<fx:Script>
		<![CDATA[
			import cart.ShoppingCart;
			import cart.ShoppingCartItem;
			
			import valueObjects.Product;
			[Bindable]
			public var product:Product;
			
			public var shoppingCart:ShoppingCart;
			
			//添加某类商品到购物车,一次添加1个
			private function addToCart(product:Product):void {
				var sci:ShoppingCartItem = new ShoppingCartItem( product );
				shoppingCart.addItem( sci );
			}
			
			//从购物车中删除该类商品,一次性全部删除
			private function removeFromCart( product:Product ):void {
				var sci:ShoppingCartItem = new ShoppingCartItem( product );
				shoppingCart.removeItem( sci );
			}
		]]>
	</fx:Script>
	
	<fx:Declarations>
		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
	</fx:Declarations>
	
	<!-- 商品 -->
	<s:VGroup  id="products"  >
		<s:Label text="{product.prodName}" id="prodName"/>
		<mx:Image source="assets/{product.imageName}" scaleContent="true" 
				  mouseOver="this.currentState='expanded'"
				  mouseOut="this.currentState='State1'"/>
		<s:Label text="${product.listPrice}" id="price"/>
		<s:Button label="AddToCart" id="add"
				  click="addToCart(product )"/>
		<s:Button label="Remove From Cart" id="remove"
				  click="removeFromCart(product )"/>			
	</s:VGroup>
	
	<!-- 商品详细信息 -->
	<s:VGroup includeIn="expanded" x="200" width="100%">
		<s:RichText text="{product.description}"
					width="50%"/>
		<s:Label text="Certified Organic"
				 visible="{product.isOrganic}"/>
		<s:Label text="Low Fat"
				 visible="{product.isLowFat}"/>
	</s:VGroup>
</s:Group>



Product.as
package valueObjects {
	[Bindable]
	public class Product {
		public var catID:Number;
		public var prodName:String;
		public var unitID:Number;
		public var cost:Number;
		public var listPrice:Number;
		public var description:String;
		public var isOrganic:Boolean;
		public var isLowFat:Boolean;
		public var imageName:String;
		
		/**
		 * 方式一:直接通过构造函数构建Product对象
		 * 
		 */		
		public function Product( catID:Number, prodName:String, unitID:Number,
								 cost:Number, listPrice:Number, description:String, isOrganic:Boolean,
								 isLowFat:Boolean, imageName:String ) { 
			this.catID = catID;
			this.prodName = prodName;
			this.unitID = unitID;
			this.cost = cost;
			this.listPrice = listPrice;
			this.description = description;
			this.isOrganic = isOrganic;
			this.isLowFat = isLowFat;
			this.imageName = imageName;
		}

		public function toString():String {
			return "[Product]" + this.prodName;
		}
		
		/**
		 * 方式二:以对象为传入参数构建Product对象 
		 * @param o
		 * @return 
		 * 
		 */		
		public static function buildProduct( o:Object ):Product {
			var p:Product;
			
			p = new Product( o.catID, o.prodName, o.unitID, o.cost,
							 o.listPrice, o.description, ( o.isOrganic == 'true' ),
							 ( o.isLowFat == 'true' ), o.imageName );
			
			return p;
		}
		/**
		 * 方式三:以XML为传入参数构建Product对象 
		 * @param data
		 * @return 
		 * 
		 */		
		public static function buildProductFromAttributes( data:XML ):Product {
			var p:Product;
			var isOrganic:Boolean = ( data.@isOrganic == "Yes" );
			var isLowFat:Boolean = ( data.@isLowFat == "Yes" );

			p = new Product( data.@catID,
				data.@prodName,
				data.@unitID,
				data.@cost,
				data.@listPrice,
				data.@description,
				isOrganic,
				isLowFat,
				data.@imageName );
			return p;
		}
	}
}


ShoppingCartItem.as
package cart {
	import valueObjects.Product;

	[Bindable]
	public class ShoppingCartItem {
		public var product:Product;//代表某类商品
		private var _quantity:uint;//添加的商品数量
		public var subtotal:Number;//总价

		public function ShoppingCartItem( product:Product, quantity:uint=1 ){
			this.product = product;
			this._quantity = quantity;
			//calculateSubtotal();
		}
		
		public function get quantity():uint
		{
			return _quantity;
		}

		public function set quantity(value:uint):void
		{
			_quantity = value;
			calculateSubtotal();//每次添加商品都会引发数量的改变,set 方法都会被调用,在这里重新计算总价
		}

		private function calculateSubtotal():void{
			this.subtotal = product.listPrice * quantity;
		}
		
		/**
		 * cartGroup中的List中,dataProvider="{shoppingCart.items}"
		 * 将会以toString返回的字符串作为列表呈现
		 * @return 
		 * 
		 */		
		public function toString():String {
			return "[ShoppingCartItem] " + product.prodName + ":" + quantity;
		}
	}
}

ShoppingCart.as
package cart {
	import mx.collections.ArrayCollection;
	import mx.collections.IViewCursor;
	import mx.collections.Sort;
	import mx.collections.SortField;

	public class ShoppingCart {
		[Bindable]
		public var items:ArrayCollection = new ArrayCollection();//所有商品都将放入此购物车

		[Bindable]
		public var total:Number = 0;//初始时购物车中商品数量为0
		/**
		 * 创建购物车的时候就指定排序规则 
		 * 排序字段按product进行排序
		 */		
		public function ShoppingCart() {
			var prodSort:Sort = new Sort();
			var sortField:SortField = new SortField( "product" );
			prodSort.fields = [ sortField ];
			items.sort = prodSort;
			items.refresh();
		}
		/**
		 * 添加商品到购物车
		 * 如果已经存在,则更新数量
		 * 否则,直接加入到购物车,默认一次添加1个 
		 * @param item
		 * 
		 */		
		public function addItem( item:ShoppingCartItem ):void {
			if ( isItemInCart( item ) ) {
				updateItem( item );
			} else {
				items.addItem( item );
			}

			calculateTotal();
		}
		/**
		 * 从购物车中删除某类商品
		 * 使用游标进行删除 
		 * @param item
		 * 
		 */		
		public function removeItem( item:ShoppingCartItem ):void {
			var cursor:IViewCursor = items.createCursor();

			if ( cursor.findFirst( item ) ) {
				cursor.remove();
			}

			calculateTotal();
		}
		
		/**
		 * 购物车中已经存在该类商品
		 * 通过cursor寻找到该商品并返回 
		 * @param item
		 * @return 如果存在,返回存在的哪个product,否则返回null
		 * 
		 */		
		private function getItemInCart( item:ShoppingCartItem ):ShoppingCartItem {
			var existingItem:ShoppingCartItem;
			var cursor:IViewCursor = items.createCursor();

			var found:Boolean = cursor.findFirst( item );

			if ( found ){
				existingItem = cursor.current as ShoppingCartItem;
			}

			return existingItem; 
		}
		
		/**
		 * 判断购物车中是否已经添加该类商品
		 * @param item
		 * @return 
		 * 
		 */		
		private function isItemInCart( item:ShoppingCartItem ):Boolean {
			var sci:ShoppingCartItem = getItemInCart( item );

			return ( sci != null );
		}
		
		/**
		 * 当购物车中已经添加过此商品,则该方法会通过逻辑判断进而被调用
		 * 更新该商品的数量 
		 * @param item
		 * 
		 */		
		private function updateItem( item:ShoppingCartItem ):void {
			var existingItem:ShoppingCartItem = getItemInCart( item );
			existingItem.quantity += item.quantity;
		}
		
		/**
		 * 统计购物车中所有商品的个数 
		 */		
		private function calculateTotal():void{
			var newTotal:Number = 0;
			var existingItem:ShoppingCartItem;

			for ( var i:uint=0; i<items.length; i++ ) {
				existingItem = items[ i ] as ShoppingCartItem;
				newTotal += existingItem.subtotal;
			}
			
			this.total = newTotal;
		}

		public function toString():String {
			return "[ShoppingCart $" + total + "] " + items;
		}
	}
}
分享到:
评论

相关推荐

    小程序自定义组件例子

    在微信小程序开发中,自定义组件是提升代码复用性和应用程序可维护性的重要工具。本示例主要关注如何创建和使用自定义组件,这对于初学者理解小程序开发流程及其内部机制非常有帮助。以下是对这个话题的详细阐述: ...

    鸿蒙+自定义组件+实例代码

    鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例鸿蒙自定义组件实例...

    android自定义组件demo

    这个"android自定义组件demo"实例提供了三种自定义组件的示例,是学习和理解Android自定义组件的一个宝贵资源。下面我们将深入探讨这三个自定义组件的关键知识点,并提供相关的实践指导。 1. **自定义View的基本...

    使用微搭自定义组件实现搜索组件 .docx

    使用微搭自定义组件实现搜索组件 微搭作为一款低代码开发平台,可以快速完成页面的搭建,但官方提供的组件可能和业务还有一定的距离。为了满足开发者的需求,微搭提供了自定义组件的能力,支持低码组件和源码组件。...

    QML自定义组件显示在QT Designer库面板中的方法

    标题《QML自定义组件显示在QT Designer库面板中的方法》涉及的知识点非常具体,主要分为以下几个方面: 首先,标题表明了文章将介绍如何将自定义的QML组件集成到QT Designer的库面板中。这种集成有利于提高开发效率...

    uniapp使用抖音微信自定义组件-uniapp如何用抖音的组件

    ### uni-app 使用抖音微信自定义组件详解 #### 一、引言 随着移动互联网的发展,跨平台应用开发框架越来越受到开发者的青睐。其中,uni-app作为一款使用Vue.js语法进行多端开发的前端框架,凭借其高效、易用的特点...

    android自定义组件简单Demo

    在Android开发中,自定义组件是一项重要的技能,它允许开发者根据特定需求创建具有独特功能和外观的视图。本教程将通过一个简单的“TestOurselfWidget”实例来讲解如何实现自定义组件。自定义组件可以增强应用的用户...

    Qt美化界面、美化组件、自定义组件源码

    "Qt美化界面、美化组件、自定义组件源码"这个主题涵盖了提升Qt应用视觉效果和功能定制的核心知识点。Qt库提供了丰富的功能,允许开发者创建出优雅且高效的应用程序,而不仅仅是基本的用户界面。 首先,Qt美化界面...

    C#自定义组件

    开发者经常需要根据项目需求创建自定义组件,以提供更个性化的界面或功能。本主题将深入探讨C#中的自定义组件,特别是关于"button"和"textlist"组件的创建和使用。 1. **自定义组件的基础** - 在C#中,自定义控件...

    Winform自定义组件库

    资源为Winform用户自定义组件库,是自己平时做项目用到的组件以及参考晚上那些有特效组件封装的组件库,中间付出了很多努力,攻克了很多难点,大家喜欢的话,请大家多多给予鼓励,目前是V1.0版本,后期不断更新。...

    Android自定义组件开发

    在Android应用开发中,自定义组件是提升用户体验和实现独特设计的重要手段。本文将深入探讨Android自定义组件的开发过程,旨在帮助开发者更好地理解和实践这一关键技能。 首先,理解Android组件的基本概念至关重要...

    【OpenHarmony】 ArkTS 语法基础 ② ( ArkTS 自定义组件 )

    【OpenHarmony】ArkTS 语法基础 ② ( ArkTS 自定义组件 | 自定义可导入组件 - export 声明模块 | 导入自定义组件 - import 导入组件 ) https://hanshuliang.blog.csdn.net/article/details/139407374 博客源码快照 ...

    各种Flex自定义组件

    在Flex中,自定义组件是开发人员为了满足特定需求而创建的特殊用户界面元素。这些组件可以扩展标准的Flex组件库,或者从头开始构建,以提供独特的功能和视觉表现。 在标题“各种Flex自定义组件”中,我们可以推断这...

    JSF2.0实战 - 4、自定义组件

    在JavaServer Faces (JSF) 2.0中,自定义组件是开发人员扩展框架功能的关键方式。通过创建自定义组件,你可以构建符合特定需求的用户界面元素,这些元素可以复用并集成到多个JSF应用程序中。本教程将深入探讨如何在...

    DELPHI中自定义组件的制作方法介绍

    ### DELPHI中自定义组件的制作方法介绍 #### 一、自定义组件的重要性与应用场景 自定义组件在DELPHI编程中扮演着至关重要的角色,它不仅能够封装复杂的功能,提升代码的可读性和可维护性,还能促进代码重用,加快...

    Flex4自定义组件开发.pdf

    ### Flex4自定义组件开发详解 #### 一、Flex4自定义组件概述 Flex4(也称为Spark)是Adobe Flex框架的一个重要版本,它引入了许多新的特性,包括改进的组件库、性能优化以及更好的可定制性。在Flex4中,自定义组件...

    android 自定义组件

    在Android开发中,自定义组件是提升应用独特性和用户体验的关键技术。自定义组件允许开发者根据需求扩展Android系统原生组件的功能,或者创建全新的组件样式,从而实现个性化界面和交互效果。下面将详细介绍Android...

    Android中自定义组件的过程

    在Android开发中,自定义组件是一项重要的技能,它允许开发者根据特定需求创建具有独特功能和外观的视图。本文将深入探讨如何在Android中自定义组件,并基于Android API Demo进行讲解,帮助你理解和掌握这一核心知识...

    基于layui自定义表单组件

    7. **自定义组件**:layui允许开发者根据需求自定义组件,扩展其功能,例如创建复杂表单控件或交互效果。 8. **响应式表单**:在移动互联网时代,layui的响应式设计使得表单在不同设备上都能良好展示,提升移动端...

    C#的自定义组件和自定义控件

    在.NET Framework中,C#提供了一个强大的平台来创建自定义组件和控件,这使得开发者可以扩展.NET Framework的基础功能,实现特定的需求。本项目聚焦于C#中的自定义组件和控件开发,涵盖了一些常见的实用功能,如速选...

Global site tag (gtag.js) - Google Analytics