AI Promptbaustein Button ausgelagert. Input State+ActionType, Output Event SelectedPrompt

AI Promptbaustein Auswahl flüssiger (IsSelected Bug)
Reset Selection bei Popup Closed
This commit is contained in:
2026-03-13 11:38:18 +01:00
parent d9242e2b0d
commit 98e06d7f47
12 changed files with 319 additions and 42 deletions

View File

@@ -155,6 +155,9 @@
<Compile Include="View\Controls\AI\AiConversationButton.xaml.cs">
<DependentUpon>AiConversationButton.xaml</DependentUpon>
</Compile>
<Compile Include="View\Controls\AI\AiPromptbausteinButton.xaml.cs">
<DependentUpon>AiPromptbausteinButton.xaml</DependentUpon>
</Compile>
<Compile Include="View\Detail\AI\AiPromptbausteinActionResultView.xaml.cs">
<DependentUpon>AiPromptbausteinActionResultView.xaml</DependentUpon>
</Compile>
@@ -256,6 +259,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\Controls\AI\AiPromptbausteinButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="View\Detail\AI\AiPromptbausteinActionResultView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View File

@@ -170,13 +170,15 @@ namespace BeWo.View.Controls.AI
{
var viewmodel = new AiPromptbausteinSelectionComplexViewModel(actionType, listvm);
viewmodel.PromptAccepted += PromptAccepted;
popup_promptbaustein_all.Closed += (s, e) => viewmodel.ResetSelection();
var view = new AiPromptbausteinComplexSelectionView(viewmodel);
view.Padding = new Thickness(3);
view.Background = FindResource("ObjectEditBackgroundBrush") as System.Windows.Media.Brush;
border_promptbaustein_al.Child = view;
var viewmodel2 = new AiPromptbausteinSelectionComplexViewModel(actionType, listvm);
var viewmodel2 = new AiPromptbausteinSelectionComplexViewModel(actionType, listvm, true);
viewmodel2.PromptAccepted += PromptAccepted;
popup_promptbaustein_favoriten.Closed += (s, e) => viewmodel2.ResetSelection();
var view2 = new AiPromptbausteinComplexSelectionView(viewmodel2);
view2.ReduceSelection();
viewmodel2.SelectedFolder = viewmodel2.Folders.VMList[0];

View File

@@ -0,0 +1,60 @@
<UserControl
x:Class="BeWo.View.Controls.AI.AiPromptbausteinButton"
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:draw="clr-namespace:System.Drawing;assembly=System.Drawing"
xmlns:local="clr-namespace:BeWo.View.Controls.AI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ai="clr-namespace:BeWo.View.Detail.AI"
x:Name="root"
mc:Ignorable="d">
<Grid>
<StackPanel
Margin="0"
VerticalAlignment="Center"
Orientation="Horizontal">
<StackPanel.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\..\..\Styles\ModernOrangeBlack.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</StackPanel.Resources>
<Button
Background="Transparent"
x:Name="btnOpenAi5"
Margin="3"
Click="btnOpenAi5_Click"
Content="{StaticResource AiDesignsIconKIFunktionWeissGruen}"
MouseRightButtonUp="btnOpenAi5_MouseRightButtonUp"
ToolTip="KI Chat mit Prompt-Baustein starten"
ToolTipService.ShowOnDisabled="True">
<!--<Button.InputBindings>
<MouseBinding Command="{Binding AiPromptOpenFavoriteCommand, ElementName=root}" Gesture="RightClick" />
<MouseBinding Command="{Binding AiPromptOpenAllCommand, ElementName=root}" Gesture="LeftClick" />
</Button.InputBindings>-->
</Button>
</StackPanel>
<Popup
x:Name="popup_promptbaustein_all"
Placement="Top"
PlacementTarget="{Binding ElementName=btnOpenAi5}"
StaysOpen="False"
Width="600"
Height="400">
<Border BorderThickness="1" x:Name="border_promptbaustein_al">
</Border>
</Popup>
<Popup
x:Name="popup_promptbaustein_favoriten"
Placement="Top"
PlacementTarget="{Binding ElementName=btnOpenAi5}"
StaysOpen="False">
<Border BorderThickness="1" x:Name="border_promptbaustein_favoriten">
</Border>
</Popup>
</Grid>
</UserControl>

View File

@@ -0,0 +1,160 @@
using BeWo.ServiceProxy;
using BeWo.View.Detail.AI;
using BeWo.ViewModel;
using BeWo.ViewModel.View.AI;
using BS.Shared;
using BS.Shared.DataContracts.Feature.AI;
using DevExpress.Utils.Mdi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
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.Navigation;
using System.Windows.Shapes;
namespace BeWo.View.Controls.AI
{
public enum AiPromptbausteinButtonState
{
Hidden,
Normal,
Loading,
Disabled
}
/// <summary>
/// Interaktionslogik für AiPromptbausteinButton.xaml
/// </summary>
public partial class AiPromptbausteinButton : UserControl
{
public static readonly DependencyProperty StateProperty =
DependencyProperty.Register("State", typeof(AiPromptbausteinButtonState), typeof(AiPromptbausteinButton), new PropertyMetadata(AiPromptbausteinButtonState.Normal, OnStateChanged));
public static readonly DependencyProperty ActionTypeProperty =
DependencyProperty.Register("ActionType", typeof(AiActionType), typeof(AiPromptbausteinButton), new PropertyMetadata(AiActionType.ServiceRecord, OnActionTypeChanged));
public event EventHandler<AiPromptbausteinPromptVM> PromptAccepted;
public AiPromptbausteinButtonState State
{
get { return (AiPromptbausteinButtonState)GetValue(StateProperty); }
set { SetValue(StateProperty, value); }
}
public AiActionType ActionType
{
get { return (AiActionType)GetValue(ActionTypeProperty); }
set { SetValue(ActionTypeProperty, value); }
}
public AiActionType LoadedActionType { get; set; }
public AiPromptbausteinButton()
{
InitializeComponent();
}
private static void OnStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (AiPromptbausteinButton)d;
var state = (AiPromptbausteinButtonState)e.NewValue;
control.UpdateState(state);
}
private static void OnActionTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (AiPromptbausteinButton)d;
var actionType = (AiActionType)e.NewValue;
control.UpdateActionType(actionType);
}
public void AiPromptOpenAll()
{
popup_promptbaustein_all.IsOpen = true;
}
public void AiPromptOpenFavorite()
{
popup_promptbaustein_favoriten.IsOpen = true;
}
private void btnOpenAi5_Click(object sender, RoutedEventArgs e)
{
AiPromptOpenAll();
}
private void btnOpenAi5_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
AiPromptOpenFavorite();
}
private void InitPromptbausteine(AiActionType actionType, List<AiPromptbausteinFolderDC> folders)
{
VMFactory.CreateAiPromptbausteinFolderListVM(folders, (listvm) =>
{
var viewmodel = new AiPromptbausteinSelectionComplexViewModel(actionType, listvm);
viewmodel.PromptAccepted += PromptAccepted;
popup_promptbaustein_all.Closed += (s, e) => viewmodel.ResetSelection();
var view = new AiPromptbausteinComplexSelectionView(viewmodel);
view.Padding = new Thickness(3);
view.Background = FindResource("ObjectEditBackgroundBrush") as System.Windows.Media.Brush;
border_promptbaustein_al.Child = view;
var viewmodel2 = new AiPromptbausteinSelectionComplexViewModel(actionType, listvm, true);
viewmodel2.PromptAccepted += PromptAccepted;
popup_promptbaustein_favoriten.Closed += (s, e) => viewmodel2.ResetSelection();
var view2 = new AiPromptbausteinComplexSelectionView(viewmodel2);
view2.ReduceSelection();
viewmodel2.SelectedFolder = viewmodel2.Folders.VMList[0];
view2.Padding = new Thickness(3);
view2.Background = FindResource("ObjectEditBackgroundBrush") as System.Windows.Media.Brush;
border_promptbaustein_favoriten.Child = view2;
State = AiPromptbausteinButtonState.Normal;
});
}
private void UpdateState(AiPromptbausteinButtonState state)
{
switch (state)
{
case AiPromptbausteinButtonState.Hidden:
root.Visibility = Visibility.Collapsed;
root.IsEnabled = true;
break;
case AiPromptbausteinButtonState.Normal:
root.Visibility = Visibility.Visible;
root.IsEnabled = true;
break;
case AiPromptbausteinButtonState.Loading:
root.Visibility = Visibility.Visible;
root.IsEnabled = false;
break;
case AiPromptbausteinButtonState.Disabled:
throw new NotImplementedException();
default:
throw new NotImplementedException();
break;
}
}
private void UpdateActionType(AiActionType actionType)
{
ActionType = actionType;
if (!BeWoApp.AppSettings.ShowAI)
{
State = AiPromptbausteinButtonState.Hidden;
return;
}
State = AiPromptbausteinButtonState.Loading;
ServiceFacade.DoAiEnhancedServiceAsnyc(x => x.GetAiPromptbausteinFolder(actionType), folders => InitPromptbausteine(actionType, folders));
}
}
}

View File

@@ -74,9 +74,9 @@
<dxe:ListBoxEdit
x:Name="listBoxEdit1"
Padding="4,16,4,16"
EditValue="{Binding SelectedPrompt, Mode=TwoWay}"
ItemContainerStyle="{StaticResource PromptListBoxItem}"
ItemsSource="{Binding SelectedFolder.Prompts, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SelectedPrompt, Mode=TwoWay}"
SelectionMode="Single">
<dxe:ListBoxEdit.ItemTemplate>
<DataTemplate>

View File

@@ -31,7 +31,18 @@ namespace BeWo.View.Detail.AI
DataContext = ViewModel = viewModel;
Loaded += (s, e) => ViewModel.InitVMList();
Loaded += (s, e) =>
{
ViewModel.InitVMList();
TreeViewItem item = treeView.ItemContainerGenerator.ContainerFromIndex(0) as TreeViewItem;
if (item != null)
{
item.IsSelected = true;
item.IsSelected = false;
}
};
}
public void ReduceSelection()

View File

@@ -1724,6 +1724,10 @@
Command="{Binding OpenAiPromptSelectionCommand}"
Content="{StaticResource AiDesignsIconKIFunktionWeissGruen}"
Style="{StaticResource PrimaryButton}" />
<ai:AiPromptbausteinButton
x:Name="btn_AiPromptbaustein2"
ActionType="ServiceRecordDocumentation"
PromptAccepted="btn_AiPromptbaustein2_PromptAccepted"/>
</StackPanel>

View File

@@ -5100,15 +5100,15 @@ namespace BeWo.View.Detail.Zeiterfassung
MainControl.WindowService.ShowAiConversationWindow(getAiConversationChatViewModel());
}
private void PromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
{
if (prompt is null)
throw new NotImplementedException();
private void PromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
{
if (prompt is null)
throw new NotImplementedException();
// 1. Information aufbereiten
// 1.1 Prompt
var prompt_oid = prompt.DataContract.Oid.Value;
var prompt_version = prompt.DataContract.Version;
// 1. Information aufbereiten
// 1.1 Prompt
var prompt_oid = prompt.DataContract.Oid.Value;
var prompt_version = prompt.DataContract.Version;
// 1.2 Restliche Informationen
var vm = getAiConversationChatViewModel();
@@ -5117,12 +5117,12 @@ namespace BeWo.View.Detail.Zeiterfassung
// 3 Auswerten
vm.MessageInput = prompt.Prompt;
vm.SendAfterLoaded = true;
vm.SendAfterLoaded = true;
MainControl.WindowService.ShowAiConversationWindow(vm);
}
MainControl.WindowService.ShowAiConversationWindow(vm);
}
private IEnumerable<ServiceRecordVM> GetVisibleRecordVMs()
private IEnumerable<ServiceRecordVM> GetVisibleRecordVMs()
{
var list = new List<ServiceRecordVM>();
@@ -5146,6 +5146,11 @@ namespace BeWo.View.Detail.Zeiterfassung
return list;
}
private void btn_AiPromptbaustein2_PromptAccepted(object sender, AiPromptbausteinPromptVM e)
{
ViewModel.PromptAccepted(sender, e);
}
}
//public class RowBackgroundHelper

View File

@@ -103,9 +103,10 @@ namespace BeWo.ViewModel
public bool IsFavorite
{
get => _IsFavorite;
set {
var success = SetProperty(ref _IsFavorite, value, nameof(IsFavorite), () => DataContract.IsFavorite);
if(success)
set
{
var success = SetProperty(ref _IsFavorite, value, nameof(IsFavorite), () => DataContract.IsFavorite);
if (success)
FirePropertyChanged(nameof(FontWeight));
}
}
@@ -124,7 +125,12 @@ namespace BeWo.ViewModel
public bool IsSelected
{
get => _IsSelected;
set => SetProperty(ref _IsSelected, value, nameof(IsInfoVisible));
set
{
var success = SetProperty(ref _IsSelected, value, nameof(IsSelected));
if (success)
FirePropertyChanged(nameof(IsInfoVisible));
}
}
public bool IsInfoVisible
@@ -190,13 +196,13 @@ namespace BeWo.ViewModel
ActionType = pDataContract.ActionType;
}
public override bool IsDirty
public override bool IsDirty
{
get
{
if (!CanEdit)
return _DirtyProps.Contains(nameof(IsFavorite));
return _DirtyProps.Count > 0;
return _DirtyProps.Count > 0;
}
}
}

View File

@@ -185,31 +185,31 @@ namespace BeWo.ViewModel.ListViewModel
private void InitAiStuff()
{
var vm_doku = new AiPromptbausteinSelectionComplexViewModel(AiActionType.ServiceRecordDocumentation);
//var vm_doku = new AiPromptbausteinSelectionComplexViewModel(AiActionType.ServiceRecordDocumentation);
vm_doku.PromptAccepted += PromptAccepted;
//vm_doku.PromptAccepted += PromptAccepted;
OpenAiPromptSelectionCommand = CommandFactory.GetAiViewCommand(
() => BeWoApp.MainControl.WindowService.Show(vm_doku),
null,
() => !string.IsNullOrWhiteSpace(AktuellerDokutext));
//OpenAiPromptSelectionCommand = CommandFactory.GetAiViewCommand(
// () => BeWoApp.MainControl.WindowService.Show(vm_doku),
// null,
// () => !string.IsNullOrWhiteSpace(AktuellerDokutext));
UndoAiActionCommand = new DelegateCommand(UndoAiAction);
RedoAiActionCommand = new DelegateCommand(RedoAiAction);
var vm_edit_doku = new AiPromptbausteinSelectionComplexViewModel(AiActionType.ServiceRecordDocumentation);
//var vm_edit_doku = new AiPromptbausteinSelectionComplexViewModel(AiActionType.ServiceRecordDocumentation);
vm_edit_doku.PromptAccepted += EditPromptAccepted;
//vm_edit_doku.PromptAccepted += EditPromptAccepted;
OpenEditAiPromptSelectionCommand = CommandFactory.GetAiViewCommand(() =>
{
_EditAiActionHistory = new List<string>();
_EditAiActionHistory.Add(AktuellerEditDokutext);
_EditAiActionHistoryIndex = 0;
BeWoApp.MainControl.WindowService.Show(vm_edit_doku);
},
null,
() => !string.IsNullOrWhiteSpace(AktuellerEditDokutext));
//OpenEditAiPromptSelectionCommand = CommandFactory.GetAiViewCommand(() =>
//{
// _EditAiActionHistory = new List<string>();
// _EditAiActionHistory.Add(AktuellerEditDokutext);
// _EditAiActionHistoryIndex = 0;
// BeWoApp.MainControl.WindowService.Show(vm_edit_doku);
//},
//null,
//() => !string.IsNullOrWhiteSpace(AktuellerEditDokutext));
UndoEditAiActionCommand = new DelegateCommand(UndoEditAiAction);
RedoEditAiActionCommand = new DelegateCommand(RedoEditAiAction);
@@ -256,7 +256,7 @@ namespace BeWo.ViewModel.ListViewModel
public bool IsEditUndoButtonVisible => _EditAiActionHistoryIndex > 0;
public bool IsEditRedoButtonVisible => _EditAiActionHistoryIndex < (_EditAiActionHistory?.Count ?? 0) - 1;
private void PromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
public void PromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
{
if (prompt is null)
throw new NotImplementedException();
@@ -363,7 +363,7 @@ namespace BeWo.ViewModel.ListViewModel
);
}
private void EditPromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
public void EditPromptAccepted(object sender, AiPromptbausteinPromptVM prompt)
{
if (prompt is null)
throw new NotImplementedException();

View File

@@ -19,6 +19,7 @@ namespace BeWo.ViewModel.View.AI
public event EventHandler<AiPromptbausteinPromptVM> PromptAccepted;
private AiPromptbausteinFolderVM _SelectedFolder;
private AiPromptbausteinPromptVM _SelectedPrompt;
public AiPromptbausteinSelectionComplexViewModel()
{
@@ -33,12 +34,15 @@ namespace BeWo.ViewModel.View.AI
{
AiActionType = aiActionType;
}
public AiPromptbausteinSelectionComplexViewModel(AiActionType aiActionType, AiPromptbausteinFolderListVM viewModel) : this(aiActionType)
public AiPromptbausteinSelectionComplexViewModel(AiActionType aiActionType, AiPromptbausteinFolderListVM viewModel, bool isFavorite = false) : this(aiActionType)
{
LoadedActionType = aiActionType;
Folders = viewModel;
IsFavorite = isFavorite;
}
public bool IsFavorite { get; set; }
public ICommand SendCommand { get; set; }
public AiActionType AiActionType { get; set; }
@@ -52,10 +56,25 @@ namespace BeWo.ViewModel.View.AI
FirePropertyChanged(nameof(SelectedFolder));
}
}
public AiPromptbausteinPromptVM SelectedPrompt { get; set; }
public AiPromptbausteinPromptVM SelectedPrompt
{
get => _SelectedPrompt;
set
{
_SelectedPrompt = value;
FirePropertyChanged(nameof(SelectedPrompt));
}
}
public AiPromptbausteinFolderListVM Folders { get; private set; }
public AiActionType LoadedActionType { get; set; }
public void ResetSelection()
{
if (!IsFavorite)
SelectedFolder = null;
SelectedPrompt = null;
}
public void Send()
{
CloseDialogCommand.Execute(null);

View File

@@ -75,6 +75,9 @@ namespace BeWo.Service.Plugins
if (model == null)
throw new NotImplementedException();
if (user_prompt == null)
user_prompt = string.Empty;
var messages = new List<string>()
{
system, user_prompt