【C#】第3章補充(二)如何將圖形作為對象

来源:http://www.cnblogs.com/rainmj/archive/2016/06/23/5609202.html
-Advertisement-
Play Games

分類:C#、VS2015 創建日期:2016-06-23 使用教材:(十二五國家級規劃教材)《C#程式設計及應用教程》(第3版) 一、要點 該例子屬於高級技術中的基本用法。對於初學者來說這是難點(難在還沒有學習第13章WPF相關的繪圖技術),因此,這裡的關鍵是理解設計思路,而不是一開始就陷於細節的實... ...


分類:C#、VS2015

創建日期:2016-06-23

使用教材:(十二五國家級規劃教材)《C#程式設計及應用教程》(第3版)

一、要點

該例子屬於高級技術中的基本用法。對於初學者來說這是難點(難在還沒有學習第13章WPF相關的繪圖技術),因此,這裡的關鍵是理解設計思路,而不是一開始就陷於細節的實現上。或者說,一旦你掌握了這些基本的設計思路,就會極大地提高你對面向對象編程的理解。

用到的技術:封裝、繼承、多態。

本補充示例的運行效果:

image

二、設計步驟

1、新建項目

項目名:WpfAdvanceDemo2

模板:WPF應用程式項目。

2、添加W0_DrawObject.cs文件

滑鼠右擊解決方案資源管理器中的項目名,選擇【添加】->【類】,輸入文件名W0_DrawObject.cs,然後將代碼改為下麵的內容:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;

namespace WpfAdvanceDemo2
{
    public abstract class W0_DrawObject : DynamicRenderer
    {
        protected Point previousPoint;

        public MyInkCanvas myInkCanvas { get; private set; }

        public DrawObjectStroke InkStroke { get; protected set; }

        public DrawingAttributes inkDA { get; set; }

        public abstract void CreateNewStroke(InkCanvasStrokeCollectedEventArgs e);

        public abstract Point Draw(Point first, DrawingContext dc, StylusPointCollection points);

        [ThreadStatic]
        protected Brush brush = Brushes.Gray;

        public W0_DrawObject(MyInkCanvas myInkCanvas)
        {
            this.myInkCanvas = myInkCanvas;
            this.inkDA = myInkCanvas.inkDA.Clone();
            this.DrawingAttributes = inkDA;
        }

        protected override void OnStylusDown(RawStylusInput rawStylusInput)
        {
            inkDA = myInkCanvas.inkDA.Clone();
            this.DrawingAttributes = inkDA;
            previousPoint = new Point(double.NegativeInfinity, double.NegativeInfinity);
            base.OnStylusDown(rawStylusInput);
        }

        protected override void OnStylusUp(RawStylusInput rawStylusInput)
        {
            base.OnStylusUp(rawStylusInput);
            this.InkStroke = null;
        }
    }

    public class DrawObjectStroke : Stroke
    {
        protected W0_DrawObject ink;

        public DrawObjectStroke(W0_DrawObject ink, StylusPointCollection stylusPoints)
            : base(stylusPoints)
        {
            this.ink = ink;
            this.DrawingAttributes = ink.inkDA.Clone();
            this.DrawingAttributes.Color = Colors.Transparent;
        }

        protected virtual void RemoveDirtyStylusPoints()
        {
            if (StylusPoints.Count > 2)
            {
                for (int i = StylusPoints.Count - 2; i > 0; i--)
                {
                    StylusPoints.RemoveAt(i);
                }
            }
        }
    }
}

3、添加W1_DrawRectangle.cs文件

滑鼠右擊解決方案資源管理器中的項目名,選擇【添加】->【類】,輸入文件名W1_DrawRectangle.cs,然後將代碼改為下麵的內容:

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;

namespace WpfAdvanceDemo2
{
    public class W1_DrawRectangle : W0_DrawObject
    {
        public W1_DrawRectangle(MyInkCanvas myInkCanvas) : base(myInkCanvas)
        {
        }

        public override void CreateNewStroke(InkCanvasStrokeCollectedEventArgs e)
        {
            InkStroke = new DrawRectangleStroke(this, e.Stroke.StylusPoints);
        }

        public override Point Draw(Point first, DrawingContext dc, StylusPointCollection points)
        {
            Point pt = (Point)points.Last();
            Vector v = Point.Subtract(pt, first);
            if (v.Length > 4)
            {
                Rect rect = new Rect(first, v);

                //填充
                var b = new RadialGradientBrush(Colors.White, Colors.Red);
                dc.DrawRectangle(b, null, rect);

                //畫輪廓
                Pen pen = new Pen(Brushes.DarkRed, 1.0);
                dc.DrawRectangle(null, pen, rect);
            }
            return first;
        }
        protected override void OnStylusDown(RawStylusInput rawStylusInput)
        {
            base.OnStylusDown(rawStylusInput);
            previousPoint = (Point)rawStylusInput.GetStylusPoints().First();
        }

        protected override void OnStylusMove(RawStylusInput rawStylusInput)
        {
            StylusPointCollection stylusPoints = rawStylusInput.GetStylusPoints();
            this.Reset(Stylus.CurrentStylusDevice, stylusPoints);
            base.OnStylusMove(rawStylusInput);
        }

        protected override void OnDraw(DrawingContext drawingContext, StylusPointCollection stylusPoints, Geometry geometry, Brush fillBrush)
        {
            Draw(previousPoint, drawingContext, stylusPoints);
            base.OnDraw(drawingContext, stylusPoints, geometry, brush);
        }
    }

    public class DrawRectangleStroke : DrawObjectStroke
    {
        public DrawRectangleStroke(W1_DrawRectangle ink, StylusPointCollection stylusPoints)
            : base(ink, stylusPoints)
        {
            this.RemoveDirtyStylusPoints();
        }

        protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
        {
            base.DrawCore(drawingContext, drawingAttributes);
            Point pt1 = (Point)StylusPoints.First();
            ink.Draw(pt1, drawingContext, StylusPoints);
        }
    }
}

4、添加W2_DrawEllipse.cs文件

滑鼠右擊解決方案資源管理器中的項目名,選擇【添加】->【類】,輸入文件名W2_DrawEllipse.cs,然後將代碼改為下麵的內容:

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns;
using System.Windows.Media;

namespace WpfAdvanceDemo2
{
    public class W2_DrawEllipse : W0_DrawObject
    {
        public W2_DrawEllipse(MyInkCanvas myInkCanvas) : base(myInkCanvas)
        {
        }

        public override void CreateNewStroke(InkCanvasStrokeCollectedEventArgs e)
        {
            InkStroke = new DrawEllipseStroke(this, e.Stroke.StylusPoints);
        }

        public override Point Draw(Point first, DrawingContext dc, StylusPointCollection points)
        {
            Point pt = (Point)points.Last();
            Vector v = Point.Subtract(pt, first);
            double radiusX = (pt.X - first.X) / 2.0;
            double radiusY = (pt.Y - first.Y) / 2.0;
            Point center = new Point((pt.X + first.X) / 2.0, (pt.Y + first.Y) / 2.0);

            //填充
            var b = new RadialGradientBrush(Colors.White, Colors.Red);
            dc.DrawEllipse(b, null, center, radiusX, radiusY);

            //畫輪廓
            Pen pen = new Pen(Brushes.DarkRed, 1.0);
            dc.DrawEllipse(null, pen, center, radiusX, radiusY);

            return first;
        }

        protected override void OnStylusDown(RawStylusInput rawStylusInput)
        {
            base.OnStylusDown(rawStylusInput);
            previousPoint = (Point)rawStylusInput.GetStylusPoints().First();
        }

        protected override void OnStylusMove(RawStylusInput rawStylusInput)
        {
            StylusPointCollection stylusPoints = rawStylusInput.GetStylusPoints();
            this.Reset(Stylus.CurrentStylusDevice, stylusPoints);
            base.OnStylusMove(rawStylusInput);
        }

        protected override void OnDraw(DrawingContext drawingContext, StylusPointCollection stylusPoints, Geometry geometry, Brush fillBrush)
        {
            Draw(previousPoint, drawingContext, stylusPoints);
            base.OnDraw(drawingContext, stylusPoints, geometry, brush);
        }
    }

    public class DrawEllipseStroke : DrawObjectStroke
    {
        public DrawEllipseStroke(W2_DrawEllipse ink, StylusPointCollection stylusPoints)
            : base(ink, stylusPoints)
        {
            this.RemoveDirtyStylusPoints();
        }

        protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
        {
            base.DrawCore(drawingContext, drawingAttributes);
            Point pt1 = (Point)StylusPoints.First();
            ink.Draw(pt1, drawingContext, StylusPoints);
        }
    }
}

5、添加W3_DrawCurve.cs文件

滑鼠右擊解決方案資源管理器中的項目名,選擇【添加】->【類】,輸入文件名W3_DrawCurve.cs,然後將代碼改為下麵的內容:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfAdvanceDemo2
{
    public class W3_DrawCurve : W0_DrawObject
    {
        public W3_DrawCurve(MyInkCanvas myInkCanvas)
            : base(myInkCanvas)
        {
        }

        public override void CreateNewStroke(InkCanvasStrokeCollectedEventArgs e)
        {
            InkStroke = new DrawCurveStroke(this, e.Stroke.StylusPoints);
        }
        public override Point Draw(Point first, DrawingContext dc, StylusPointCollection points)
        {
            return first;
        }

        protected override void OnDraw(DrawingContext drawingContext, StylusPointCollection stylusPoints, Geometry geometry, Brush fillBrush)
        {
            base.OnDraw(drawingContext, stylusPoints, geometry, Brushes.Black);
        }
    }

    public class DrawCurveStroke : DrawObjectStroke
    {
        public DrawCurveStroke(W0_DrawObject ink, StylusPointCollection stylusPoints)
            : base(ink, stylusPoints)
        {
            this.DrawingAttributes.FitToCurve = true;
        }

        protected override void DrawCore(DrawingContext drawingContext, DrawingAttributes drawingAttributes)
        {
            base.DrawCore(drawingContext, drawingAttributes);
            Geometry geometry = this.GetGeometry();
            drawingContext.DrawGeometry(Brushes.Black, null, geometry);
        }
    }
}

6、添加MyInkCanvas.cs文件

滑鼠右擊解決方案資源管理器中的項目名,選擇【添加】->【類】,輸入文件名MyInkCanvas.cs,然後將代碼改為下麵的內容:

using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfAdvanceDemo2
{
    public class MyInkCanvas : InkCanvas
    {
        private W0_DrawObject ink;

        public DrawingAttributes inkDA { get; private set; }

        public MyInkCanvas()
        {
            inkDA = new DrawingAttributes()
            {
                Color = Colors.Red,
                Width = 15,
                Height = 15,
                StylusTip = StylusTip.Rectangle,
                IgnorePressure = true,
                FitToCurve = false
            };
            this.DefaultDrawingAttributes = inkDA;
            ink = new W1_DrawRectangle(this);
            UpdateInkParams();
        }

        /// <summary>當收集墨跡時,會自動調用此方法</summary>
        protected override void OnStrokeCollected(InkCanvasStrokeCollectedEventArgs e)
        {
            this.Strokes.Remove(e.Stroke);
            ink.CreateNewStroke(e);
            this.Strokes.Add(ink.InkStroke);
            InkCanvasStrokeCollectedEventArgs args = new InkCanvasStrokeCollectedEventArgs(ink.InkStroke);
            base.OnStrokeCollected(args);
        }

        /// <summary>初始化墨跡參數</summary>
        public void SetInkAttributes(string name)
        {
            switch (name)
            {
                //---------------墨跡類型---------------------
                case "矩形":
                    ink = new W1_DrawRectangle(this);
                    inkDA.Width = inkDA.Height = 15;
                    inkDA.StylusTip = StylusTip.Rectangle;
                    this.UseCustomCursor = false;
                    break;
                case "球形":
                    ink = new W2_DrawEllipse(this);
                    inkDA.Width = inkDA.Height = 15;
                    inkDA.StylusTip = StylusTip.Ellipse;
                    this.UseCustomCursor = false;
                    break;
                case "毛筆":
                    ink = new W3_DrawCurve(this);
                    inkDA.Width = inkDA.Height = 10;
                    this.Cursor = Cursors.Pen;
                    this.UseCustomCursor = true;
                    break;
            }
            UpdateInkParams();
        }

        /// <summary>
        /// 根據墨跡類型和筆尖信息,設置MyInkCanvas中的相關參數
        /// </summary>
        private void UpdateInkParams()
        {
            this.DynamicRenderer = ink;
            this.EditingMode = InkCanvasEditingMode.Ink;
        }
    }
}

7、修改MainWindow.xaml文件

將其改為下麵的內容。

<Window x:Class="WpfAdvanceDemo2.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:WpfAdvanceDemo2"
        mc:Ignorable="d"
        Title="將圖形作為對象--簡單示例(http://cnblogs.com/rainmj)" Height="400" Width="700" WindowStartupLocation="CenterScreen" Background="#FFE4EEDE">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0">
            <TextBlock Text="提示:選擇一種繪製類型,然後在繪圖框區域內按住滑鼠左鍵拖動繪製。" Margin="0 20" FontSize="16" Foreground="Blue" VerticalAlignment="Center" HorizontalAlignment="Center"/>
            <Separator/>
            <WrapPanel ButtonBase.Click="RadioButton_Click" Margin="0 10 0 0">
                <TextBlock Text="繪製類型:" VerticalAlignment="Center"/>
                <RadioButton Content="矩形" IsChecked="True" Margin="5"/>
                <RadioButton Content="球形" Margin="5"/>
                <RadioButton Content="毛筆" Margin="5"/>
            </WrapPanel>
        </StackPanel>
        <Frame Name="frame1" Grid.Row="1" Margin="10" BorderThickness="1" BorderBrush="Blue"
                   NavigationUIVisibility="Hidden" />
        <TextBlock Grid.Row="2" Text="(完整例子在【網路應用編程】課程中還會介紹,該例子僅演示了最基本的用法)" Margin="0 0 0 5" VerticalAlignment="Center" HorizontalAlignment="Center"/>
    </Grid>
</Window>

8、修改MainWindow.xaml.cs文件

將其改為下麵的內容。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace WpfAdvanceDemo2
{
    /// <summary>
    /// MainWindow.xaml 的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        MyInkCanvas mycanvas;
        public MainWindow()
        {
            InitializeComponent();
            mycanvas = new MyInkCanvas();
            frame1.Content = mycanvas;
        }

        private void RadioButton_Click(object sender, RoutedEventArgs e)
        {
            string s = (e.Source as RadioButton).Content.ToString();
            mycanvas.SetInkAttributes(s);
        }
    }
}

9、運行

按<F5>鍵調試運行。

OK,這個例子雖然簡單,但是卻演示了封裝、繼承、多態在實際項目中的基本應用設計思路。請耐著性子仔細分析該例子的源代碼,相信你掌握設計思路和技巧後一定會對C#面向對象編程的理解有一個大的飛躍。

在此基礎上,你就可以繼續學習複雜的例子了。實際上,任何內容都可以通過拖放繪製出來,包括視頻。

三、高級用法

下麵的截圖演示了高級用法示例的運行效果(選擇某種繪圖類型以及其他選項後,按住滑鼠左鍵隨意拖放即可):

image

該例子更接近於實際項目,雖然例子看起來好像很複雜,但是基本的設計思路還是這個簡單例子的思路,只不過是在簡單例子基礎上多添加了一些類而已。

這裡順便解釋一下,類似Office的工具箱界面是如何實現的(用到了Ribbon控制項):

(1)滑鼠右擊【引用】->【添加引用】,然後按下圖所示添加Ribbon引用。

image

(2)在項目中添加一個Windows窗體,然後就可以在該窗體中使用Ribbon控制項設計工具箱的內容了。下麵是高級例子對應的XAML代碼(為了方便快速理解,這裡去掉了重覆的內容,僅列出了其中的一部分代碼):

<Window x:Class="WpfExamples.ch03.Ex02.WpfAdvanceDemo3.Demo3MainWindow"
        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:WpfExamples.ch03.Ex02.WpfAdvanceDemo3"
        mc:Ignorable="d"
        Title="將圖形圖像作為對象--高級功能" Height="460" Width="980" Background="#FFF0F9D8" WindowState="Maximized">
    <Grid x:Name="root">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Ribbon Name="ribbon" Grid.Row="0">
            <Ribbon.Resources>
                <Style TargetType="RibbonRadioButton">
                    <Setter Property="LargeImageSource" Value="/Resources/Images/b1.png"/>
                    <Setter Property="SmallImageSource" Value="/Resources/Images/b1.gif"/>
                    <Setter Property="CornerRadius" Value="13"/>
                    <Setter Property="Margin" Value="5 0 0 0"/>
                    <EventSetter Event="Checked" Handler="RibbonRadioButton_Checked"/>
                </Style>
            </Ribbon.Resources>
            <Ribbon.ApplicationMenu>
                <RibbonApplicationMenu Name="appMenu1" ToolTip="主菜單">
                    <RibbonApplicationMenu.Resources>
                        <Style TargetType="RibbonApplicationMenuItem">
                            <Setter Property="ImageSource" Value="/Resources/Images/b1.gif"/>
                            <EventSetter Event="Click" Handler="RibbonApplicationMenuItem_Click"/>
                        </Style>
                    </RibbonApplicationMenu.Resources>
                    <RibbonApplicationMenuItem Header="打開"/>
                    <RibbonApplicationMenuItem Header="另存為"/>
                    <RibbonSeparator/>
                    <RibbonApplicationMenuItem Header="退出"/>
                </RibbonApplicationMenu>
            </Ribbon.ApplicationMenu>

            <RibbonTab Name="rt1" Header="工具箱">
                <RibbonGroup Header="墨跡類型">
                    <RibbonGroup.GroupSizeDefinitions>
                        <RibbonGroupSizeDefinition>
                            <RibbonControlSizeDefinition ImageSize="Small"/>
                            <RibbonControlSizeDefinition ImageSize="Small"/>
                            ......(略,內容都一樣,個數與下麵的RibbonRadioButton個數對應即可)
                        </RibbonGroupSizeDefinition>
                    </RibbonGroup.GroupSizeDefinitions>
                    <RibbonRadioButton x:Name="rrbEllipseType" Label="球形" IsChecked="True"/>
                    <RibbonRadioButton Label="矩形"/>
                    <RibbonRadioButton Label="圖像"/>
                    <RibbonRadioButton Label="球形序列"/>
                    <RibbonRadioButton Label="矩形序列"/>
                    <RibbonRadioButton Label="圖像序列"/>
                    <RibbonRadioButton Label="直線"/>
                    <RibbonRadioButton Label="曲線"/>
                    <RibbonRadioButton Label="文字"/>
                </RibbonGroup>
                <RibbonGroup Header="筆尖類型">
                    <RibbonRadioButton x:Name="rrbEllipseStylus" Label="圓筆" IsChecked="True" GroupName="edit" />
                    <RibbonRadioButton Label="豎筆" GroupName="edit"/>
                    <RibbonRadioButton Label="橫筆" GroupName="edit"/>
                    <RibbonRadioButton Label="鋼筆" GroupName="edit"/>
                </RibbonGroup>
                .....(後面的代碼和前面類似,不再列出了)
            </RibbonTab>
        </Ribbon>
        <Grid x:Name="grid1" Margin="10" Grid.Row="1" Visibility="Visible">
            <Rectangle Grid.ColumnSpan="2" Fill="white"
                       RadiusX="14" RadiusY="14"
                       Stroke="Blue" StrokeDashArray="3" />
            <local:MyInkCanvas x:Name="ink1"/>
        </Grid>
    </Grid>
</Window>

註意:練習時要一行一行的敲,不要用複製粘貼的辦法,否則系統不會自動在後臺代碼(代碼隱藏類)中添加對應的事件處理程式。

在後續的章節中,我們還會學習該高級例子涉及的更多概念(比如利用序列化和反序列化將繪圖結果保存到文件中,並將序列化後的結果讀取出來還原為截圖中的各個繪圖對象等)。這裡暫不列出高級例子的設計步驟,準備等後續章節把相關的概念介紹完畢後,再學習高級例子的源代碼也不晚。

說明:這些例子全部都是本人原創的,轉載請註明出處:http://cnblogs.com/rainmj

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Linux代碼的重用: 在頭文件中載入即可使用到原來所有的功能,還有動態方式就是一個驅動使用另一個驅動的資源。 對於像蜂鳴器這樣的實驗,它的內部文件有很多,所有要有很多的源代碼以用於妥善管理。 有多個文件的話,module-y指定所有的文件,然後將會生成一個build.sh腳本,使用sh執行,使用d ...
  • 我們知道在Linux伺服器上,可以安裝多個版本的JDK,那麼當有多個JDK時,是否可以為Tomcat這類應用程式指定對應的JDK版本呢?答案是可以,指定tomcat使用特定的JDK版本。今天正好碰到這個問題,總結一下。方便以後遇到這類問題。 1:在tomcat的catalina.sh文件中加入 ex... ...
  • 最近學習了elf文件的格式,重點關註了動態鏈接過程中的使用到的section 第一步程式在載入時,會把解釋器程式加入到.interp段。可以解決動態庫和可執行文件的載入。 一般來講程式的載入方式是懶啟動,Lazy;除非指定了LD_BIND_NOW環境變數非0,那麼在程式啟動時就會把外部符號地址全部加 ...
  • 在這個練習中,我們來學習如何把我們想要的東西寫到文件中。我們在這個練習中還是使用File類中的方法來完成寫文件的操作。 在這個練習中我們要用C#創建一個純文本文件ex11.txt 放到c盤的Exercise11目錄下。通常c盤下是沒有Exercise11目錄的,請先建立這個目錄。我們的C#程式會讓用 ...
  • 1. 為什麼使用正則表達式? 典型的搜索和替換操作要求您提供與預期的搜索結果匹配的確切文本。雖然這種技術對於對靜態文本執行簡單搜索和替換任務可能已經足夠了,但它缺乏靈活性,若採用這種方法搜索動態文本,即使不是不可能,至少也會變得很困難。通過使用正則表達式,可以: ※ 測試字元串內的模式。 例如,可以 ...
  • WebApi框架,可分為三層:托管層、消息處理程式托管層、控制器處理層。 一、托管層: 即Host,是WebAPI宿主,如:控制台,Windows服務等。 寄宿方式。 1、定製托管。 2、自托管。 3、Web托管 Owin寄宿 ,如Katana, 在一個Owin相容的伺服器上建立一個WebApi層, ...
  • MD5簡介: MD5的全稱是Message-Digest Algorithm 5,在90年代初由MIT的電腦科學實驗室和RSA Data Security Inc發明,經MD2、MD3和MD4發展而來。MD5將任意長度的“位元組串”變換成一個128bit的大整數,並且它是一個不可逆的字元串變換演算法。 ...
  • ASP.NET支持以下驗證控制項 RequiredFieldValidator(非空驗證) 確保用戶沒有跳過輸入控制項。RequiredFieldValidator控制項可以與文本框綁定在一起,以便強制用戶對文本框進行輸入。使用選擇控制項,例如,對於下拉框控制項和單選按鈕,RequiredFieldValid ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...