国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

基于Avalonia 11.0.0+ReactiveUI 的跨平臺項(xiàng)目開發(fā)2-功能開發(fā)

這篇具有很好參考價值的文章主要介紹了基于Avalonia 11.0.0+ReactiveUI 的跨平臺項(xiàng)目開發(fā)2-功能開發(fā)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

基于Avalonia 11.0.0+ReactiveUI 的跨平臺項(xiàng)目開發(fā)2-功能開發(fā)

項(xiàng)目簡介:目標(biāo)是開發(fā)一個跨平臺的AI聊天和其他功能的客戶端平臺。目的來學(xué)習(xí)和了解Avalonia。將這個項(xiàng)目部署在openKylin 1.0 的系統(tǒng)上。

為什么使用Avalonia:之前已經(jīng)了解了基于Avalonia的項(xiàng)目在國產(chǎn)麒麟系統(tǒng)中運(yùn)行的案例。正是Avalonia在跨平臺的出色表現(xiàn),學(xué)習(xí)和了解Avalonia這個UI框架顯得十分有必要。本項(xiàng)目采用的是最新穩(wěn)定版本11.0.0-rc1.1。希望通過該項(xiàng)目了解和學(xué)習(xí)Avalonia開發(fā)的朋友可以在我的github上拉取代碼,同時希望大家多多點(diǎn)點(diǎn)star。

https://github.com/raokun/TerraMours.Chat.Ava

項(xiàng)目的基礎(chǔ)框架和通用功能在上一篇博客中介紹過了,想了解的同學(xué)跳轉(zhuǎn)學(xué)習(xí):

基于Avalonia 11.0.0+ReactiveUI 的跨平臺項(xiàng)目開發(fā)1-通用框架

了解Avalonia創(chuàng)建模板項(xiàng)目-基礎(chǔ)可跳轉(zhuǎn):

創(chuàng)建Avalonia 模板項(xiàng)目-基礎(chǔ)

本次我主要分享的內(nèi)容是項(xiàng)目中具體功能開發(fā)實(shí)現(xiàn)的過程和各技術(shù)的應(yīng)用

1.功能介紹

1.界面交互

第一版的內(nèi)容主要分為以下幾個模塊:

  • LoadView.axaml 加載界面:系統(tǒng)打開時候的加載界面,用于首頁替換的技術(shù)實(shí)踐??筛脑斐傻顷懡缑?。
  • MainWindow.axaml 首頁
  • MainView.axaml 主界面
  • DataGridView.axaml 會話列表
  • ChatView.axaml 聊天界面
  • ApiSettingsView.axaml API配置

2.功能實(shí)現(xiàn)

下面我會按照各個模塊來介紹對應(yīng)的功能和實(shí)現(xiàn)方法。

1.加載界面

加載界面 是系統(tǒng)的首個加載界面,界面樣式如下:

1.作用和功能:

加載界面是系統(tǒng)在運(yùn)行前的準(zhǔn)備界面,目前并沒有做什么操作,只是做了個進(jìn)度條,到100%時跳轉(zhuǎn)首頁。不過這是一個可擴(kuò)展的實(shí)踐。

加載界面完成了首頁的切換的實(shí)踐,為后期登錄頁面做好了準(zhǔn)備。同時,加載界面的內(nèi)容,改寫成蒙版,在需要長時間數(shù)據(jù)處理用于限制用戶操作也是不錯的選擇。

2.設(shè)置加載界面為項(xiàng)目運(yùn)行時首個加載界面

設(shè)置首個加載界面,需要在App.axaml.cs中的OnFrameworkInitializationCompleted方法中設(shè)置 desktop.MainWindow

OnFrameworkInitializationCompleted代碼如下:

public override void OnFrameworkInitializationCompleted() {
    //添加共享資源
    var VMLocator = new VMLocator();
    Resources.Add("VMLocator", VMLocator);

    if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
        var load= new LoadView {
            DataContext = new LoadViewModel(),
        };
        desktop.MainWindow = load;
        VMLocator.LoadViewModel.ToMainAction = () =>
        {
            desktop.MainWindow = new MainWindow();
            desktop.MainWindow.Show();
            load.Close();
        };

    }

    base.OnFrameworkInitializationCompleted();
}

3.隱藏窗口的關(guān)閉按鈕,并設(shè)置窗口居中顯示

加載界面不應(yīng)該有關(guān)閉等按鈕,我們用 SystemDecorations="None"。將 SystemDecorations 屬性設(shè)置為 "None" 可以隱藏窗口的系統(tǒng)裝飾。系統(tǒng)裝飾包括標(biāo)題欄、最小化、最大化和關(guān)閉按鈕等。通過設(shè)置 SystemDecorations"None",可以使窗口更加定制化和個性化,同時減少了不必要的系統(tǒng)裝飾。

界面應(yīng)該顯示在屏幕正中間。我們用 WindowStartupLocation="CenterScreen"。設(shè)置 WindowStartupLocation"CenterScreen" 可以使窗口在屏幕上居中顯示。

4.實(shí)現(xiàn)進(jìn)度條

代碼如下:

<StackPanel
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Orientation="Vertical"
            Spacing="10">
    <TextBlock
               Text="Loading..."
               HorizontalAlignment="Center"
               VerticalAlignment="Center"
               Foreground="White"
               Background="Transparent"/>
    <ProgressBar
                 x:Name="progressBar"
                 HorizontalAlignment="Center"
                 Minimum="0"
                 Maximum="100"
                 Value="{Binding Progress}"
                 Width="200"
                 Height="20"
                 Background="Transparent">
        <ProgressBar.Foreground>
            <SolidColorBrush Color="White"/>
        </ProgressBar.Foreground>
    </ProgressBar>
</StackPanel>

進(jìn)度條用到了ProgressBar 的控件,對應(yīng)的官方文檔地址:ProgressBar

控件的屬性:

Property Description
Minimum 最大值
Maximum 最小值
Value 當(dāng)前值
Foreground 進(jìn)度條顏色
ShowProgressText 顯示進(jìn)度數(shù)值

Value 值通過Binding綁定了ViewModel中的屬性字段Progress。通過UpdateProgress()方法,讓Progress的值由0變化到100,模擬加載過程。

代碼如下:

private async void UpdateProgress() {
    // 模擬登錄加載過程
    for (int i = 0; i <= 100; i++) {
        Progress = i;
        await Task.Delay(100); // 延遲一段時間,以模擬加載過程
    }
    ToMainAction?.Invoke();
}

5.加載完成后跳轉(zhuǎn)首頁

界面的跳轉(zhuǎn),通過Action委托來完成,首先在LoadViewModel中定義 ToMainAction,在上面的UpdateProgress方法完成時執(zhí)行Invoke,而ToMainAction的實(shí)現(xiàn)方法,寫在OnFrameworkInitializationCompleted方法中。

ToMainAction的實(shí)現(xiàn)方法中,將desktop.MainWindow變更成MainWindowloadView隱藏,MainWindow顯示。

2.首頁+API配置

加載界面 是承載程序的界面,界面樣式如下:

1.作用和功能:

首頁 主要作用是承載程序的界面,每一個Avalonia項(xiàng)目在創(chuàng)建時會自動創(chuàng)建MainWindow.axaml 在界面axaml中很簡單。承載了MainView 的用戶控件,和API設(shè)置界面。

首頁 包括控制API設(shè)置的數(shù)據(jù)交互、鍵盤的監(jiān)聽事件、系統(tǒng)語言的判斷。

API配置 包括用于OpenAI接口調(diào)用參數(shù)的全部設(shè)置。

2.界面設(shè)計-設(shè)置彈框

代碼如下:

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="using:TerraMours.Chat.Ava.ViewModels"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="TerraMours.Chat.Ava.Views.MainWindow"
		x:DataType="vm:MainWindowViewModel"
		xmlns:dialogHost="clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia"
		RenderOptions.BitmapInterpolationMode="HighQuality"
		xmlns:sty="using:FluentAvalonia.Styling"
		xmlns:ui="using:FluentAvalonia.UI.Controls"
		xmlns:local="using:TerraMours.Chat.Ava.Views"
        Icon="/Assets/terramours.ico"
        Title="TerraMours.Chat.Ava">
	<dialogHost:DialogHost IsOpen="{Binding	ApiSettingIsOpened}"
						   DialogMargin="16"
							DisableOpeningAnimation="True"
						   dialogHost:DialogHostStyle.CornerRadius="8"
						   Background="rgb(52, 53, 65)">
		<dialogHost:DialogHost.DialogContent>
			<local:ApiSettingsView />
		</dialogHost:DialogHost.DialogContent>

		<Panel>
			<local:MainView />
		</Panel>

	</dialogHost:DialogHost>

</Window>

界面中使用到了 DialogHost.Avalonia,做彈框的簡單實(shí)現(xiàn)。IsOpen 控制彈窗的顯隱性。DialogHost.DialogContent 中填入彈框的顯示內(nèi)容。顯示內(nèi)容為

ApiSettingsView。

而主體部分只有一個Panel,包含著MainView,這使得MainView的界面會占滿整個程序界面。至此,首頁的界面設(shè)計就完成了。

Icon="/Assets/terramours.ico" 設(shè)置了程序的logo,如下:

3.初始化

MainWindow 在界面加載時要做很多工作。MainWindow的構(gòu)造函數(shù)如下:

代碼如下:

public MainWindow() {
            InitializeComponent();
            this.Closing += (sender, e) => SaveWindowSizeAndPosition();

            this.Loaded += MainWindow_Loaded;
            MainWindowViewModel = new MainWindowViewModel();
            VMLocator.MainWindowViewModel = MainWindowViewModel;
            DataContext = MainWindowViewModel;
            var cultureInfo = CultureInfo.CurrentCulture;
            if (cultureInfo.Name == "zh-CN") {
                Translate("zh-CN");
            }

            this.KeyDown += MainWindow_KeyDown;

        }

MainWindow的構(gòu)造函數(shù)綁定了多個事件的實(shí)現(xiàn)方法:

  1. this.Loaded 界面加載時觸發(fā)MainWindow_Loaded 方法,作用是加載本地數(shù)據(jù)和本地配置文件。
  2. this.Closing 程序關(guān)閉時觸發(fā)SaveWindowSizeAndPosition方法,作用是保存當(dāng)前的系統(tǒng)設(shè)置,包括用戶調(diào)整后的界面的長寬和在屏幕的位置,用戶下次打開時程序還會出現(xiàn)在之前的位置。比如,我把系統(tǒng)拉到桌面左上角,把窗口縮小到最小尺寸時候退出程序,下次打開,程序界面還會在之前退出的位置,在桌面左上角以最小尺寸出現(xiàn)。
  3. this.KeyDown 監(jiān)聽鍵盤的輸入事件,當(dāng)按鍵按下時,會觸發(fā)MainWindow_KeyDown方法,用于綁定自定義的快捷鍵。

MainWindow構(gòu)造函數(shù)中,通過判斷CultureInfo.CurrentCulture,獲取當(dāng)前 操作系統(tǒng)的語言系統(tǒng),判斷程序應(yīng)該顯示哪個國家的語言。從而確定程序顯示的語言,通過Translate 修改語言相關(guān)配置。是系統(tǒng)國際化的實(shí)踐。

4.系統(tǒng)配置-本地保存和加載

系統(tǒng)配置 對應(yīng)AppSettings類,記錄了應(yīng)用程序設(shè)置ChatGPT API參數(shù)

系統(tǒng)設(shè)置參數(shù)通過保存到文件settings.json中實(shí)現(xiàn)配置的本地化和持久化。

MainWindow_Loaded 的方法實(shí)現(xiàn)系統(tǒng)配置加載:

代碼如下:

private async void MainWindow_Loaded(object sender,RoutedEventArgs e) {
    var settings = await LoadAppSettingsAsync();

    if (File.Exists(Path.Combine(settings.AppDataPath, "settings.json"))) {
        this.Width = settings.Width - 1;
        this.Position = new PixelPoint(settings.X, settings.Y);
        this.Height = settings.Height;
        this.Width = settings.Width;
        this.WindowState = settings.IsMaximized ? WindowState.Maximized : WindowState.Normal;
    }
    else {
        var screen = Screens.Primary;
        var workingArea = screen.WorkingArea;

        double dpiScaling = screen.PixelDensity;
        this.Width = 1300 * dpiScaling;
        this.Height = 840 * dpiScaling;

        this.Position = new PixelPoint(5, 0);
    }


    if (!File.Exists(settings.DbPath)) {
        _dbProcess.CreateDatabase();
    }

    await _dbProcess.DbLoadToMemoryAsync();
    await VMLocator.MainViewModel.LoadPhraseItemsAsync();

    VMLocator.MainViewModel.SelectedPhraseItem = settings.PhrasePreset;

    VMLocator.MainViewModel.SelectedLogPain = "Chat List";

    await Dispatcher.UIThread.InvokeAsync(() => { VMLocator.MainViewModel.LogPainIsOpened = false; });
    if (this.Width > 1295) {
        //await Task.Delay(1000);
        await Dispatcher.UIThread.InvokeAsync(() => { VMLocator.MainViewModel.LogPainIsOpened = true; });
    }

    this.GetObservable(ClientSizeProperty).Subscribe(size => OnSizeChanged(size));
    _previousWidth = ClientSize.Width;

    await _dbProcess.UpdateChatLogDatabaseAsync();


    await _dbProcess.CleanUpEditorLogDatabaseAsync();

    if (string.IsNullOrWhiteSpace(VMLocator.MainWindowViewModel.ApiKey)) {
        var dialog = new ContentDialog() { Title = $"Please enter your API key.", PrimaryButtonText = "OK" };
        await VMLocator.MainViewModel.ContentDialogShowAsync(dialog);
        VMLocator.ChatViewModel.OpenApiSettings();
    }
}

MainWindow_Loaded 的方法中,通過解析settings.json,加載系統(tǒng)配置。

settings.json 的解析和保存

相關(guān)方法如下:

至此,系統(tǒng)配置的開發(fā)就基本完成了。對于這些不需要遠(yuǎn)程同步的基礎(chǔ)配置,保存在本地文件中。

5.國際化

通過Translate方法,根據(jù)當(dāng)前系統(tǒng)語言,改變控制文字顯示的資源文件,實(shí)現(xiàn)語言的切換。

代碼如下:

public void Translate(string targetLanguage) {
    var translations = App.Current.Resources.MergedDictionaries.OfType<ResourceInclude>().FirstOrDefault(x => x.Source?.OriginalString?.Contains("/Lang/") ?? false);

    if (translations != null)
        App.Current.Resources.MergedDictionaries.Remove(translations);

    App.Current.Resources.MergedDictionaries.Add(
        (ResourceDictionary)AvaloniaXamlLoader.Load(
            new Uri($"avares://TerraMours.Chat.Ava/Assets/lang/{targetLanguage}.axaml")
        )
    );
}

關(guān)于國際化的資源文件的創(chuàng)建請看前篇內(nèi)容:基于Avalonia 11.0.0+ReactiveUI 的跨平臺項(xiàng)目開發(fā)1-通用框架

3.主界面

主界面 是項(xiàng)目的核心,包括了以下圖片所有內(nèi)容的布局,它勾勒出了整個程序。中間包括左上角的圖標(biāo),會話列表,聊天區(qū)域,查詢,配置等等。

1.作用和功能

主界面 的作用,是顯示和完成整個業(yè)務(wù)功能的展示和交互。主界面 將會話列表和聊天窗口左右分開??刂屏苏麄€程序的排版和布局。

主要分三塊:

  1. 程序標(biāo)題logo
  2. 會話列表
  3. 聊天窗口

2.界面設(shè)計

具體代碼不貼出來了,需要了解的同學(xué)可以fork項(xiàng)目代碼查看,功能區(qū)已經(jīng)標(biāo)注注釋了,方便查看。

3.SplitView控制會話列表顯示

會話列表聊天窗口 通過SplitView 實(shí)現(xiàn),會話列表在窗口縮小時自動隱藏。通過IsPaneOpen屬性控制。

隱藏效果:

實(shí)現(xiàn)方法為OnSizeChanged方法:

代碼如下:

 private void OnSizeChanged(Size newSize) {
     if (_previousWidth != newSize.Width) {
         if (newSize.Width <= 1295) {
             VMLocator.MainViewModel.LogPainIsOpened = false;
             VMLocator.MainViewModel.LogPainButtonIsVisible = false;
         }
         else {
             if (VMLocator.MainViewModel.LogPainButtonIsVisible == false) {
                 VMLocator.MainViewModel.LogPainButtonIsVisible = true;
             }
             if (newSize.Width > _previousWidth) {
                 VMLocator.MainViewModel.LogPainIsOpened = true;
             }
         }
         _previousWidth = newSize.Width;
     }
 }

當(dāng)窗口寬度小于1295,會修改VMLocator.MainViewModel.LogPainButtonIsVisible為false,實(shí)現(xiàn)會話列表隱藏的效果。

4.初始化

MainViewModel控制了程序大部分的按鍵的事件實(shí)現(xiàn),MainViewModel的構(gòu)造函數(shù)如下:

代碼如下:

 public MainViewModel() {
     PostButtonText = "Post";

     LoadChatListCommand = ReactiveCommand.CreateFromTask<string>(async (keyword) => await LoadChatListAsync(keyword));
     PhrasePresetsItems = new ObservableCollection<string>();

     //會話
     ImportChatLogCommand = ReactiveCommand.CreateFromTask(ImportChatLogAsync);
     ExportChatLogCommand = ReactiveCommand.CreateFromTask(ExportChatLogAsync);
     DeleteChatLogCommand = ReactiveCommand.CreateFromTask(DeleteChatLogAsync);
     //配置
     SystemMessageCommand = ReactiveCommand.Create(InsertSystemMessage);
     HotKeyDisplayCommand = ReactiveCommand.CreateFromTask(HotKeyDisplayAsync);
     OpenApiSettingsCommand = ReactiveCommand.Create(OpenApiSettings);
     ShowDatabaseSettingsCommand = ReactiveCommand.CreateFromTask(ShowDatabaseSettingsAsync);
     //聊天
     PostCommand = ReactiveCommand.CreateFromTask(PostChatAsync);
 }

其中,綁定了會話、配置、聊天等功能的按鈕事件。實(shí)現(xiàn)業(yè)務(wù)的交互。

5.調(diào)用ChatGpt接口

通過Betalgo.OpenAI 完成接口調(diào)用,是一個開源的nuget包,集成了OpenAI的接口,簡化了調(diào)用邏輯。

本來更傾向于Senmantic Kernel的,是微軟開發(fā)的LLM訓(xùn)練框架,但是代理方面我還沒有很好的解決辦法,后面再替換。

接口調(diào)用方法寫在PostChatAsync方法里,通過post按鈕發(fā)起調(diào)用:

代碼如下:

/// <summary>
/// OpenAI 調(diào)用方法
/// </summary>
/// <returns></returns>
private async Task PostChatAsync()
{
    try
    {
        string message = PostMessage;
        int conversationId = 1;
        //創(chuàng)建會話
        if(VMLocator.DataGridViewModel.ChatList == null)
        {
            VMLocator.DataGridViewModel.ChatList=new ObservableCollection<ChatList> ();
            VMLocator.DataGridViewModel.ChatList.Add(new ChatList() { Id=1,Title=(message.Length< 5?message:$"{message.Substring(0,5)}..."), Category = (message.Length < 5 ? message : $"{message.Substring(0, 5)}...") ,Date=DateTime.Now});
        }
        if (VMLocator.ChatViewModel.ChatHistory == null)
            VMLocator.ChatViewModel.ChatHistory = new ObservableCollection<Models.ChatMessage>();
        VMLocator.ChatViewModel.ChatHistory.Add(new Models.ChatMessage() { ChatRecordId = 1, ConversationId = conversationId, Message = message, Role = "User", CreateDate = DateTime.Now });

        //根據(jù)配置中的CONTEXT_COUNT 查詢上下文
        var messages = new List<OpenAI.ObjectModels.RequestModels.ChatMessage>();
        messages.Add(OpenAI.ObjectModels.RequestModels.ChatMessage.FromUser(message));
        var openAiOpetions = new OpenAI.OpenAiOptions()
        {
            ApiKey = AppSettings.Instance.ApiKey,
            BaseDomain = AppSettings.Instance.ApiUrl
        };
        var openAiService = new OpenAIService(openAiOpetions);
        //調(diào)用SDK
        var response = await openAiService.ChatCompletion.CreateCompletion(new ChatCompletionCreateRequest
                                                                           {
                                                                               Messages = messages,
                                                                               Model = AppSettings.Instance.ApiModel,
                                                                               MaxTokens = AppSettings.Instance.ApiMaxTokens,
                                                                           });
        if (response == null)
        {
            var dialog = new ContentDialog()
            {
                Title = "接口調(diào)用失敗",
                PrimaryButtonText = "Ok"
            };
            await VMLocator.MainViewModel.ContentDialogShowAsync(dialog);
        }
        if (!response.Successful)
        {
            var dialog = new ContentDialog()
            {
                Title = $"接口調(diào)用失敗,報錯內(nèi)容: {response.Error.Message}",
                PrimaryButtonText = "Ok"
            };
            await VMLocator.MainViewModel.ContentDialogShowAsync(dialog);
        }
        VMLocator.ChatViewModel.ChatHistory.Add(new Models.ChatMessage() { ChatRecordId = 2, ConversationId = conversationId, Message = response.Choices.FirstOrDefault().Message.Content, Role = "Assistant", CreateDate = DateTime.Now });
        VMLocator.MainViewModel.PostMessage = "";
    }
    catch (Exception e)
    {
    }
}

通過創(chuàng)建OpenAIService初始化,Completion接口調(diào)用時使用openAiService.ChatCompletion.CreateCompletion方法。

ChatMessage是上下文的模型,通過創(chuàng)建messages完成上下文的創(chuàng)建,請求參數(shù)都寫在ChatCompletionCreateRequest之中。

目前的第一版使用的CreateCompletion是直接返回的結(jié)果。后面我會優(yōu)化調(diào)用,使用Stream流式輸出。

4.會話列表

會話列表是模擬chatgpt官網(wǎng)的樣式,將聊天按會話的形式歸類。chatgpt官網(wǎng)截圖如下:

1.作用和功能

會話列表將聊天按會話的形式歸類,更好的管理聊天內(nèi)容。

2.界面設(shè)計

因?yàn)榭紤]到后面會有其他類型的AI 類型,決定通過DataGrid實(shí)現(xiàn)會話列表,DataGrid的表格類型也能更多的展示數(shù)據(jù)。

代碼如下:

<UserControl xmlns="https://github.com/avaloniaui"
             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"
             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
			 xmlns:vm="using:TerraMours.Chat.Ava.ViewModels"
		     x:DataType="vm:DataGridViewModel"
			 xmlns:local="using:TerraMours.Chat.Ava"
             x:Class="TerraMours.Chat.Ava.Views.DataGridView">
	<UserControl.Resources>
		<local:CustomDateConverter x:Key="CustomDateConverter" />
	</UserControl.Resources>
	<Grid>
		<DataGrid Name="ChatListDataGrid"
				  ItemsSource="{Binding ChatList}"
				  AutoGenerateColumns="False"
				  HeadersVisibility="None"
				  SelectionMode="Single"
				  SelectedItem="{Binding SelectedItem}"
				  SelectedIndex="{Binding SelectedItemIndex}">
			<DataGrid.Columns>
				<DataGridTextColumn Binding="{Binding Id}" IsVisible="False"/>
				<DataGridTextColumn Foreground="rgb(155,155,155)"
								  FontSize="12"
									Binding="{Binding Date,Converter={StaticResource CustomDateConverter},Mode=OneWay}"
									IsReadOnly="True"/>
				<DataGridTextColumn Binding="{Binding Title}" IsReadOnly="True"/>
			</DataGrid.Columns>
		</DataGrid>
	</Grid>
</UserControl>

會話列表的數(shù)據(jù)共有三個:Id,創(chuàng)建時間,會話標(biāo)題。通過DataGridTextColumn 通過綁定的形式實(shí)現(xiàn)。

其中,使用了CustomDateConverter 時間轉(zhuǎn)換器,將Date的顯示格式做轉(zhuǎn)換。

3.數(shù)據(jù)交互

會話列表目前還在優(yōu)化,第一版是通過第一次調(diào)用PostChatAsync時創(chuàng)建的。目前的數(shù)據(jù)存在本地SQLite數(shù)據(jù)庫中。

5.聊天窗口

聊天窗口是程序的工作重心,是展示聊天成果的重要界面。其中用到Markdown.Avalonia的擴(kuò)展包實(shí)現(xiàn)Markdown內(nèi)容的展示。

1.作用和功能

數(shù)據(jù)是核心,聊天窗口是數(shù)據(jù)的展示平臺,作用不容小噓。通過編寫數(shù)據(jù)模板DataTemplate來控制內(nèi)容的展示。呈現(xiàn)chat問答式的結(jié)果。

2.Markdown 風(fēng)格樣式

通過DataTemplate來設(shè)置Markdown 風(fēng)格樣式。代碼如下:

<DataTemplate>
    <Border
    Name="MessageBorder"
    Background="{Binding Role, Converter={StaticResource ChatBackgroundConverter}}"
    HorizontalAlignment="Left"
    Padding="5"
    Margin="20,5,20,20"
    CornerRadius="8,8,8,0">
    <md:MarkdownScrollViewer
        VerticalAlignment="Stretch"
        MarkdownStyleName="Standard"
        SaveScrollValueWhenContentUpdated="True"
        TextElement.FontSize="16"
        TextElement.Foreground="White"
        Markdown="{Binding Message}">
        <md:MarkdownScrollViewer.Styles>
            <Style Selector="ctxt|CCode">
            <Style.Setters>
            <Setter Property="BorderBrush"         Value="Green"/>
            <Setter Property="BorderThickness"     Value="2"/>
            <Setter Property="Padding"             Value="2"/>
            <Setter Property="MonospaceFontFamily" Value="Meiryo" />
            <Setter Property="Foreground"          Value="DarkGreen" />
            <Setter Property="Background"          Value="LightGreen" />
            </Style.Setters>
            </Style>

            <Style Selector="Border.CodeBlock">
            <Style.Setters>
            <Setter Property="BorderBrush" Value="#E2E6EA" />
            <Setter Property="BorderThickness" Value="0,30,0,0" />
            <Setter Property="Margin" Value="5,0,5,0" />
            <Setter Property="Background" Value="Black" />
            </Style.Setters>
            </Style>

            <Style Selector="TextBlock.CodeBlock">
            <Style.Setters>
            <Setter Property="Background" Value="Black" />
            </Style.Setters>
            </Style>

            <Style Selector="avedit|TextEditor">
            <Style.Setters>
            <Setter Property="BorderBrush" Value="#E2E6EA" />
            <Setter Property="Background" Value="Black" />
            <Setter Property="Padding" Value="5"></Setter>
            </Style.Setters>
            </Style>

            </md:MarkdownScrollViewer.Styles>
                <md:MarkdownScrollViewer.ContextMenu>
                    <ContextMenu Padding="3">
                    <MenuItem>
                    <MenuItem.Header>
                    <TextBlock>編輯</TextBlock>
                    </MenuItem.Header>
                    </MenuItem>
                    <!--<MenuItem Tag="{Binding ChatRecordId}" Click="DeleteClick">
                    <MenuItem.Header>
                    <TextBlock>刪除</TextBlock>
                    </MenuItem.Header>
                    </MenuItem>
                    <MenuItem Tag="{Binding Message}" Click="CopyClick">
                    <MenuItem.Header>
                    <TextBlock>復(fù)制</TextBlock>
                    </MenuItem.Header>
                    </MenuItem>-->
                    </ContextMenu>
                    </md:MarkdownScrollViewer.ContextMenu>
                        </md:MarkdownScrollViewer>
                            </Border>
                            </DataTemplate>

MarkdownScrollViewer.Styles 根據(jù)不同的內(nèi)容設(shè)置不同的樣式。

MarkdownScrollViewer.ContextMenu設(shè)置右鍵菜單。

其中通過ChatBackgroundConverter轉(zhuǎn)換器根據(jù)角色控制背景,ChatBackgroundConverter代碼如下:

3.總結(jié)和待辦事項(xiàng)

avalonia開發(fā)目前網(wǎng)上,特別是國內(nèi)的網(wǎng)站的教程和文章很少,希望能給大家一點(diǎn)學(xué)習(xí)使用avalonia開發(fā)客戶端項(xiàng)目的朋友一點(diǎn)幫助。寫的不對的地方也懇請大家多多留言,我會及時更正,多多交流心得體會。

Todo:

  1. 項(xiàng)目發(fā)布,在多平臺下的運(yùn)行
  2. 搭建國產(chǎn)系統(tǒng)虛擬機(jī)測試avalonia項(xiàng)目
  3. 程序改造成云同步版本,跟我做的web項(xiàng)目互通。
  4. 優(yōu)化UI界面
  5. 優(yōu)化語言國際化內(nèi)容

**目前程序還沒有完全開發(fā)完成。后續(xù)的開發(fā)我會及時跟進(jìn)。閱讀如遇樣式問題,請前往個人博客瀏覽:https://www.raokun.top

目前web端ChatGPT:https://ai.terramours.site

當(dāng)前開源項(xiàng)目地址:https://github.com/raokun/TerraMours.Chat.Ava文章來源地址http://www.zghlxwxcb.cn/news/detail-583391.html

到了這里,關(guān)于基于Avalonia 11.0.0+ReactiveUI 的跨平臺項(xiàng)目開發(fā)2-功能開發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Avalonia學(xué)習(xí)實(shí)踐(二)--跨平臺支持及發(fā)布

    Avalonia學(xué)習(xí)實(shí)踐(二)--跨平臺支持及發(fā)布

    Avalonia主打跨平臺,號稱一套代碼支持Windows, macOS, Linux, iOS, Android操作系統(tǒng),其基礎(chǔ)是基于.NET Standard 2.0的一系列庫,也就是只要平臺能支持.NET Standard 2.0,就能運(yùn)行Avalonia開發(fā)的應(yīng)用。然而理想很豐滿、現(xiàn)實(shí)很骨感,并不是說跨平臺Avalonia沒有做到,而是過程中免不了會有些小

    2024年02月07日
    瀏覽(86)
  • 探索Avalonia:C#跨平臺UI框架的力量

    探索Avalonia:C#跨平臺UI框架的力量

    隨著跨平臺應(yīng)用的需求不斷增長,開發(fā)人員需要一種能夠在不同操作系統(tǒng)上運(yùn)行的用戶界面(UI)框架。 Avalonia 是一種引人注目的選擇。在本文中,我們將深入了解 Avalonia 是什么,它與 WPF 的區(qū)別,以及它的 UI 繪制引擎和原理、優(yōu)點(diǎn),以及一個簡單的示例代碼。 Avalonia 是什

    2024年04月08日
    瀏覽(93)
  • Net跨平臺UI框架Avalonia入門-安裝和使用

    Net跨平臺UI框架Avalonia入門-安裝和使用

    Avalonia UI是是Net的跨平臺UI框架,支持 Windows、Linux、iOS 和 Android,與Net其他UI框架相比,如WPF(Windows平臺)、MAUI跨平臺控件(Android、iOS、macOS 和 Windows),主要優(yōu)勢是支持Linux。在國產(chǎn)化的需求下,對于C#開發(fā)的程序員,Avalonia適合用來開發(fā)Linux的桌面客戶端。 v11版本已經(jīng)發(fā)布

    2024年02月05日
    瀏覽(94)
  • .NET / C# 開發(fā) Ubuntu Desktop 跨平臺圖形界面桌面程序 Avalonia - Visual Studio 安裝/創(chuàng)建/運(yùn)行指南 (一)

    .NET / C# 開發(fā) Ubuntu Desktop 跨平臺圖形界面桌面程序 Avalonia - Visual Studio 安裝/創(chuàng)建/運(yùn)行指南 (一)

    Avalonia 是一個開源的跨平臺應(yīng)用程序框架,用于構(gòu)建桌面應(yīng)用程序。它使用 C# 和 XAML 進(jìn)行開發(fā),可以在 Windows、macOS、iOS、Android 及 Linux 等多個平臺上運(yùn)行。Avalonia 項(xiàng)目地址:https://github.com/AvaloniaUI/Avalonia 本文快速介紹如何入門使用 Avalonia 編寫和執(zhí)行 Ubuntu Desktop 圖形界面桌面

    2024年02月01日
    瀏覽(105)
  • 跨平臺應(yīng)用開發(fā)進(jìn)階(六十二):如何把 uni-app APP項(xiàng)目轉(zhuǎn)換成小程序

    隨著移動互聯(lián)網(wǎng)的快速發(fā)展,移動應(yīng)用已成為生活中不可或缺的一部分。與此同時,跨平臺開發(fā)也得到越來越多的關(guān)注,因?yàn)樗梢蕴岣邞?yīng)用程序的效率并降低開發(fā)成本。 uni-app 是一種跨平臺開發(fā)框架,基于 Vue.js ,并且可以在多個平臺如微信小程序、支付寶小程序、H5等上運(yùn)

    2024年02月15日
    瀏覽(37)
  • 跨平臺應(yīng)用開發(fā)進(jìn)階(五十)uni-app ios web-view嵌套H5項(xiàng)目白屏問題分析及解決

    跨平臺應(yīng)用開發(fā)進(jìn)階(五十)uni-app ios web-view嵌套H5項(xiàng)目白屏問題分析及解決

    應(yīng)用 uni-app 框架開發(fā)好APP上架使用過程中,發(fā)現(xiàn)應(yīng)用經(jīng)過長時間由后臺切換至前臺時,通過 webview 方式嵌套的H5頁面發(fā)生白屏現(xiàn)象。 任何手機(jī)設(shè)備上,當(dāng)手機(jī)內(nèi)存不足時,os都會回收資源。一般是先回收后臺打開的資源。如果當(dāng)前應(yīng)用占用的資源過高,當(dāng)前應(yīng)用也有可能崩潰

    2024年02月14日
    瀏覽(24)
  • 關(guān)于 Delphi 11.3跨平臺開發(fā)Android調(diào)用 JNI JAR java 的說明和注意事項(xiàng)

    關(guān)于 調(diào)用 JNI JAR 的說明和注意事項(xiàng),調(diào)用第三方 JAR SDK 和 翻譯 安卓 JAVA 代碼 的說明 V2017.10.18 (* ************************************************ *) (* *) (* *) (* 設(shè)計:愛吃豬頭肉 Flying Wang 2015-04-15 ?*) (* 上面的版權(quán)聲明請不要移除。 *) (* *) (* ************************************************ *) 本人所

    2024年02月07日
    瀏覽(27)
  • 一個基于.NET Core開源、跨平臺的倉儲管理系統(tǒng)

    一個基于.NET Core開源、跨平臺的倉儲管理系統(tǒng)

    今天給大家推薦一個基于.NET Core開源、跨平臺的倉儲管理系統(tǒng),數(shù)據(jù)庫支持MSSQL/MySQL:ZEQP.WMS。 倉儲管理系統(tǒng)(Warehouse Management System,WMS)是一種用于管理和控制倉庫操作的軟件系統(tǒng),它可以幫助企業(yè)實(shí)現(xiàn)對倉庫內(nèi)物品的跟蹤、存儲、揀選、包裝和發(fā)運(yùn)等全過程管理,提高倉

    2024年02月21日
    瀏覽(913)
  • 基于 FFMPEG 的跨平臺視頻播放器簡明教程(三):視頻解碼

    基于 FFmpeg 的跨平臺視頻播放器簡明教程(一):FFMPEG + Conan 環(huán)境集成 基于 FFmpeg 的跨平臺視頻播放器簡明教程(二):基礎(chǔ)知識和解封裝(demux) 在前面章節(jié) 基于 FFMPEG 的跨平臺視頻播放器簡明教程(二):基礎(chǔ)知識和解封裝(demux) 中我們引入了視頻編解碼的基礎(chǔ)知識以

    2024年02月08日
    瀏覽(112)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包