使用C#开发ChatGPT聊天程序

简介: 最近ChatGPT比较火,大多是用python开发的,今天使用wpf来开发一款ChatGPT聊天程序

使用C#开发ChatGPT聊天程序

总体效果如下:

关键点1:无边框窗口拖动

Window中设置AllowsTransparency="True"Background="Transparent"以及WindowStyle="None"这样设置的话默认窗口的标题栏为不可见状态,且无法用鼠标拖动,使用windowChorme来解决

<WindowChrome.WindowChrome>

   <WindowChromeCaptionHeight="50"UseAeroCaptionButtons="False"/>

</WindowChrome.WindowChrome>

该设置的详细讲解参见WPF之Window无边框拖动、特殊形状、Grid拖拽

关键点2:输入栏实现删除按钮

  1. 定义TextBox的ControlTemplate模板(节取重要部分)

<Stylex:Key="TextBoxPromote"TargetType="{x:Type TextBox}">

           <SetterProperty="Template">

               <Setter.Value>

                   <ControlTemplateTargetType="{x:Type TextBox}">

                       <Border

                           x:Name="border"

                           CornerRadius="6"

                           <DockPanel LastChildFill="True">

                           <!--新增btn按钮,并绑定Click事件-->

                               <Button

                                   x:Name="btn"

                                   Grid.Column="1"

                                   Background="White"

                                   BorderThickness="0"

                                   Click="Button_Click"

                                   Content="&#xe8d5;"

                                   DockPanel.Dock="Right"

                                   FontFamily="./img/#iconfont"/>

                               <ScrollViewer

                                   x:Name="PART_ContentHost"

                                   DockPanel.Dock="Left"

                                   Focusable="false"

                                   HorizontalScrollBarVisibility="Hidden"

                                   VerticalScrollBarVisibility="Hidden"/>

                           </DockPanel>

                       </Border>

                       <ControlTemplate.Triggers>

                          <!--新增DataTrigger,当Text属性部位为空时,不显示按钮,Hiddern表示不显示,但是用空格来代替按钮来保持布局,而Collapsed则是不显示且不保留空格-->

                           <DataTriggerBinding="{Binding RelativeSource={RelativeSource Self}, Path=Text}"Value="">

                               <SetterTargetName="btn"Property="Visibility"Value="Collapsed"/>

                           </DataTrigger>

                       </ControlTemplate.Triggers>

                   </ControlTemplate>

               </Setter.Value>

           </Setter>

       </Style>

  1. 实现Button按钮事件

privatevoidButton_Click(objectsender, RoutedEventArgse)

{

   Button?btn=senderasButton;

   if (btn!=null)

   {

       varparent=VisualTreeHelper.GetParent(btn);

       while (!(parentisTextBox))

       {

           parent=VisualTreeHelper.GetParent(parent);

       }

       TextBoxtxt=parentasTextBox;

       if (txt!=null)

       {

           txt.Clear();

       }

   }

}

关键点3:ListBox实现聊天效果

本文使用ListBox来完成消息框的展示,因为涉及到发送和收到两种类型的消息,应该对应两种不同格式,所以会用到样式选择器,不知道怎么用的小伙伴可以看一下这篇文章WPF控件模板、数据模板、容器样式选择器

  1. 定义选择器类

publicclassDateTemplateSelector:DataTemplateSelector

{

   publicDataTemplateSendTemplate { get; set; }

   publicDataTemplateResTemplate { get; set; }

   publicoverrideDataTemplateSelectTemplate(objectitem, DependencyObjectcontainer)

   {

       Messagemessage= (Message)item;

       if (message.IsSend)

       {

           returnSendTemplate;

       }

       else

       {

           returnResTemplate;

       }

   }

}

  1. 在Windwo.Resources中定义数据模板

发送模板

<DataTemplatex:Key="chatSend">

   <StackPanel

       x:Name="SendMsg"

       Margin="0,12,20,0"

       HorizontalAlignment="Right"

       Orientation="Horizontal">

       <StackPanelMargin="0,0,10,0"Orientation="Vertical">

           <!--  消息内容  -->

           <Border

               MinWidth="50"

               MinHeight="30"

               MaxWidth="{Binding Path=ActualWidth,ElementName=borderWidth}"

               Background="#c8dd1f"

               BorderBrush="#ddd"

               BorderThickness="1"

               CornerRadius="8,0,8,8">

               <TextBox

                   MinWidth="30"

                   Margin="8"

                   VerticalAlignment="Center"

                   Background="Transparent"

                   BorderThickness="0"

                   FontSize="14"

                   IsReadOnly="True"

                   Text="{Binding Msg}"

                   TextWrapping="WrapWithOverflow"/>

           </Border>

       </StackPanel>

       <!--  头像  -->

       <Border

           Width="35"

           Height="35"

           Margin="0,2,0,0"

           VerticalAlignment="Top"

           BorderThickness="0">

           <Border.Background>

               <ImageBrushImageSource="/img/user.jpg"/>

           </Border.Background>

       </Border>

   </StackPanel>

</DataTemplate>

接收模板

<DataTemplatex:Key="chatRes">

   <StackPanel

       x:Name="SendMsg"

       Margin="0,12,20,0"

       HorizontalAlignment="Right"

       Orientation="Horizontal">

       <!--  头像  -->

       <Border

                   Width="35"

                   Height="35"

                   Margin="0,2,0,0"

                   VerticalAlignment="Top"

                   BorderThickness="0">

                   <Border.Background>

                       <ImageBrushImageSource="/img/图标ChatGPT.ico"/>

                   </Border.Background>

               </Border>

       <StackPanelMargin="0,0,10,0"Orientation="Vertical">

           <!--  消息内容  -->

           <Border

               MinWidth="50"

               MinHeight="30"

               MaxWidth="{Binding Path=ActualWidth,ElementName=borderWidth}"

               Background="#c8dd1f"

               BorderBrush="#ddd"

               BorderThickness="1"

               CornerRadius="0,8,8,8">

               <TextBox

                   MinWidth="30"

                   Margin="8"

                   VerticalAlignment="Center"

                   Background="Transparent"

                   BorderThickness="0"

                   FontSize="14"

                   IsReadOnly="True"

                   MaxLength="25"

                   Text="{Binding Msg}"

                   TextWrapping="WrapWithOverflow"/>

           </Border>

       </StackPanel>

   </StackPanel>

</DataTemplate>

  1. 因为发送消息和接受消息的对齐方式不同,一个是左一个是右,所以要定义下ListBox.ItemContainerStyle

<Stylex:Key="listViewItemStyle"TargetType="{x:Type ListBoxItem}">

   <SetterProperty="FocusVisualStyle"Value="{x:Null}"/>

   <SetterProperty="Template">

       <Setter.Value>

           <ControlTemplateTargetType="{x:Type ListBoxItem}">

               <Border

                   Name="Bd"

                   Margin="1"

                   Padding="{TemplateBinding Padding}"

                   Background="{TemplateBinding Background}"

                   BorderBrush="{TemplateBinding BorderBrush}"

                   BorderThickness="{TemplateBinding BorderThickness}"

                   SnapsToDevicePixels="true">

                   <ContentPresenter

                       Margin="1"

                       HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"

                       VerticalAlignment="{TemplateBinding VerticalContentAlignment}"

                       SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>

               </Border>

           </ControlTemplate>

       </Setter.Value>

   </Setter>

   <!--判断是否为发送,从而使用不同的对齐方式-->

   <Style.Triggers>

       <DataTriggerBinding="{Binding IsSend}"Value="True">

           <SetterProperty="HorizontalContentAlignment"Value="Stretch"/>

       </DataTrigger>

       <DataTriggerBinding="{Binding IsSend}"Value="False">

           <SetterProperty="HorizontalContentAlignment"Value="Left"/>

       </DataTrigger>

   </Style.Triggers>

</Style>

  1. 为了实现ListBox始终保持下拉到最后的状态,自定义类,重写OnItemsChanged方法

classScrollingListBox : ListBox

{

   protectedoverridevoidOnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgse)

   {

       if (e.NewItems==null) return;

       varnewItemCount=e.NewItems.Count;

       if (newItemCount>0)

           this.ScrollIntoView(e.NewItems[newItemCount-1]);

       base.OnItemsChanged(e);

   }

}

  1. XAML中设置

<!--  消息显示区  -->

<!--设置ScrollViewer.CanContentScroll="False"可以使得滚动条更加丝滑-->

<local:ScrollingListBox

   Grid.Row="0"

   BorderBrush="#D3D3D3"

   BorderThickness="0,1,0,1"

   ItemsSource="{Binding Path=Messages, ElementName=mainWindow}"

   ScrollViewer.HorizontalScrollBarVisibility="Disabled"

   ScrollViewer.CanContentScroll="False"

   SelectionMode="Extended">

   <ListBox.ItemTemplateSelector>

       <local:DateTemplateSelector ResTemplate="{StaticResource chatRes}" SendTemplate="{StaticResource chatSend}" />

   </ListBox.ItemTemplateSelector>

   <ListBox.ItemContainerStyle>

       <Style BasedOn="{StaticResource listViewItemStyle}" TargetType="{x:Type ListBoxItem}" />

   </ListBox.ItemContainerStyle>

</local:ScrollingListBox>


相关文章
|
27天前
|
缓存 C# Windows
C#程序如何编译成Native代码
【10月更文挑战第15天】在C#中,可以通过.NET Native和第三方工具(如Ngen.exe)将程序编译成Native代码,以提升性能和启动速度。.NET Native适用于UWP应用,而Ngen.exe则通过预编译托管程序集为本地机器代码来加速启动。不过,这些方法也可能增加编译时间和部署复杂度。
|
5天前
|
人工智能 自然语言处理 自动驾驶
深入理解ChatGPT:下一代人工智能助手的开发与应用
【10月更文挑战第27天】本文深入探讨了ChatGPT的技术原理、开发技巧和应用场景,展示了其在语言理解和生成方面的强大能力。文章介绍了基于Transformer的架构、预训练与微调技术,以及如何定制化开发、确保安全性和支持多语言。通过实用工具如GPT-3 API和Fine-tuning as a Service,开发者可以轻松集成ChatGPT。未来,ChatGPT有望在智能家居、自动驾驶等领域发挥更大作用,推动人工智能技术的发展。
|
5天前
|
测试技术 Go C#
C#一分钟浅谈:ReSharper 插件增强开发效率
【10月更文挑战第25天】ReSharper 是 JetBrains 开发的一款 Visual Studio 插件,旨在提高 .NET 开发者的生产力。它通过代码分析、重构、导航等功能,帮助开发者避免常见错误,提升代码质量和开发效率。本文将通过具体代码案例,详细介绍 ReSharper 的常见功能及其应用。
14 1
|
11天前
|
C# Python
使用wxpython开发跨平台桌面应用,对wxpython控件实现类似C#扩展函数处理的探究
【10月更文挑战第30天】使用 `wxPython` 开发跨平台桌面应用时,可以通过创建辅助类来模拟 C# 扩展函数的功能。具体步骤包括:1. 创建辅助类 `WxWidgetHelpers`;2. 在该类中定义静态方法,如 `set_button_color`;3. 在应用中调用这些方法。这种方法提高了代码的可读性和可维护性,无需修改 `wxPython` 库即可为控件添加自定义功能。但需要注意显式调用方法和避免命名冲突。
|
18天前
|
JSON C# 开发者
C#语言新特性深度剖析:提升你的.NET开发效率
【10月更文挑战第15天】C#语言凭借其强大的功能和易用性深受开发者喜爱。随着.NET平台的演进,C#不断引入新特性,如C# 7.0的模式匹配和C# 8.0的异步流,显著提升了开发效率和代码可维护性。本文将深入探讨这些新特性,助力开发者在.NET开发中更高效地利用它们。
28 1
|
25天前
|
开发框架 NoSQL MongoDB
C#/.NET/.NET Core开发实战教程集合
C#/.NET/.NET Core开发实战教程集合
|
18天前
|
设计模式 程序员 C#
C# 使用 WinForm MDI 模式管理多个子窗体程序的详细步骤
WinForm MDI 模式就像是有超能力一般,让多个子窗体井然有序地排列在一个主窗体之下,既美观又实用。不过,也要小心管理好子窗体们的生命周期哦,否则一不小心就会出现一些意想不到的小bug
|
1月前
|
XML 存储 安全
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
C#开发的程序如何良好的防止反编译被破解?ConfuserEx .NET混淆工具使用介绍
44 0
|
1月前
|
iOS开发 MacOS Python
ChatGPT编程实现简易聊天工具
ChatGPT编程实现简易聊天工具
|
1月前
|
安全 API C#
C# 如何让程序后台进程不被Windows任务管理器强制结束
C# 如何让程序后台进程不被Windows任务管理器强制结束
58 0