Hallo,
Ich bin Hobbyprogrammierer (meist nach der Arbeit, wenn ich dann noch Zeit hab und nicht zu müde bin) und ganz neu in WPF (ich habe vorher nur komplexere Weblösungen (aspx) mit VB.Net programmiert) und habe jetzt mit einiger Hilfestellung ein kleines Programm geschrieben, das Daten aus SQLite ausliest und in einem Datagrid mit Richtextboxen in 2 von 3 Spalten auflistet. Von den 3 Spalten kann der Benutzer die 2 mit den RTBs bearbeiten. Leider schaffe ich es seit Wochen nicht, diese Änderungen wieder auszulesen, um sie dann in SQLite zu speichern.
Ich habe dazu in diversen englishsprachigen Foren einen Richtextboxhelper "vorgesetzt" bekommen, den ich teilweise umbauen musste, damit die Daten noch vor Anzeigen etwas formatiert werden. Dies greift, soweit ich es verstanden habe, direkt nachdem die RTB-Felder befüllt werden. Die ganzen Zusammenhänge verstehe ich leider noch nicht ganz.
Nun möchte ich idealerweise beim Anklicken einer Schaltfläche die veränderten RTBs auslesen und in SQLite speichern. Leider kann ich nicht auf die Daten aus den RTBs zugreifen, im MS-Forum checken die einfach nicht, dass es RTBs und keine normalen Textboxes sind und die ganzen Lösungsvorschläge mit INotifyPropertyChanged und ObservableCollection funktionieren daher nicht.
Alternativ hab ich mir überlegt die Daten über den Helper zu verarbeiten, wenn der Benutzer das Feld verlässt (lost focus), aber ich verstehe nicht ganz wie ich den Helper auslösen kann.
Hier mal mein Code, vielleicht kann ja wer weiterhelfen:
XAML:
codebehind:
Helper:
Befüllen des Datagrids über DataTable:
Solltet Ihr noch etwas zusätzlichen Code zum besseren Nachvollziehen benötigen, bitte melden.
LG,
Pascal
Ich bin Hobbyprogrammierer (meist nach der Arbeit, wenn ich dann noch Zeit hab und nicht zu müde bin) und ganz neu in WPF (ich habe vorher nur komplexere Weblösungen (aspx) mit VB.Net programmiert) und habe jetzt mit einiger Hilfestellung ein kleines Programm geschrieben, das Daten aus SQLite ausliest und in einem Datagrid mit Richtextboxen in 2 von 3 Spalten auflistet. Von den 3 Spalten kann der Benutzer die 2 mit den RTBs bearbeiten. Leider schaffe ich es seit Wochen nicht, diese Änderungen wieder auszulesen, um sie dann in SQLite zu speichern.
Ich habe dazu in diversen englishsprachigen Foren einen Richtextboxhelper "vorgesetzt" bekommen, den ich teilweise umbauen musste, damit die Daten noch vor Anzeigen etwas formatiert werden. Dies greift, soweit ich es verstanden habe, direkt nachdem die RTB-Felder befüllt werden. Die ganzen Zusammenhänge verstehe ich leider noch nicht ganz.
Nun möchte ich idealerweise beim Anklicken einer Schaltfläche die veränderten RTBs auslesen und in SQLite speichern. Leider kann ich nicht auf die Daten aus den RTBs zugreifen, im MS-Forum checken die einfach nicht, dass es RTBs und keine normalen Textboxes sind und die ganzen Lösungsvorschläge mit INotifyPropertyChanged und ObservableCollection funktionieren daher nicht.
Alternativ hab ich mir überlegt die Daten über den Helper zu verarbeiten, wenn der Benutzer das Feld verlässt (lost focus), aber ich verstehe nicht ganz wie ich den Helper auslösen kann.
Hier mal mein Code, vielleicht kann ja wer weiterhelfen:
XAML:
VB.NET-Quellcode
- <Window x:Class="Window1"
- xmlns="[url]http://schemas.microsoft.com/winfx/2006/xaml/presentation[/url]"
- xmlns:x="[url]http://schemas.microsoft.com/winfx/2006/xaml[/url]"
- xmlns:d="[url]http://schemas.microsoft.com/expression/blend/2008[/url]"
- xmlns:mc="[url]http://schemas.openxmlformats.org/markup-compatibility/2006[/url]"
- xmlns:local="clr-namespace:TMEdit"
- mc:Ignorable="d"
- Title="Window1" WindowState="Maximized" WindowStartupLocation="CenterScreen" d:DesignWidth="1412.668" d:DesignHeight="532.284">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="217*"/>
- <RowDefinition Height="284*"/>
- </Grid.RowDefinitions>
- <Button x:Name="Button1" Content="Hinzufügen" HorizontalAlignment="Left" Margin="26,53,0,0" VerticalAlignment="Top" Width="97" Visibility="visible"/>
- <DataGrid x:Name="DG1" Margin="10,124,10,10" ItemsSource="{Binding}" HorizontalContentAlignment="Stretch" AutoGenerateColumns="False" Grid.RowSpan="2" CanUserAddRows="False">
- <DataGrid.Columns>
- <DataGridTextColumn Header="Id" Binding="{Binding id}" Width="Auto"></DataGridTextColumn>
- <DataGridTemplateColumn Header="source_segment" Width="50*">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <local:RichTextBoxHelper x:Name="rtb" VerticalScrollBarVisibility="Auto" keytoken ="13" TextValue="{Binding source_segment}">
- </local:RichTextBoxHelper>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- <DataGridTemplateColumn.CellStyle>
- <Style>
- <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
- </Style>
- </DataGridTemplateColumn.CellStyle>
- </DataGridTemplateColumn>
- <DataGridTemplateColumn Header="target_segment" Width="50*">
- <DataGridTemplateColumn.CellTemplate>
- <DataTemplate>
- <local:RichTextBoxHelper x:Name="rtb" VerticalScrollBarVisibility="Auto" keytoken ="11" TextValue="{Binding target_segment, Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
- </local:RichTextBoxHelper>
- </DataTemplate>
- </DataGridTemplateColumn.CellTemplate>
- <DataGridTemplateColumn.CellStyle>
- <Style>
- <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
- </Style>
- </DataGridTemplateColumn.CellStyle>
- </DataGridTemplateColumn>
- </DataGrid.Columns>
- </DataGrid>
- <TextBox x:Name="TB1" HorizontalAlignment="Left" Height="23" Margin="183,11,0,0" TextWrapping="Wrap" Text="Suchtext für Ausgangstext" LostKeyboardFocus="TextBox_LostKeyboardFocus" GotKeyboardFocus="TextBox_GotKeyboardFocus" KeyUp="TextBox_KeyUp" VerticalAlignment="Top" Width="341" Visibility="visible"/>
- <TextBox x:Name="TB2" HorizontalAlignment="Left" Height="23" Margin="183,46,0,0" TextWrapping="Wrap" Text="Suchtext für Zieltext" LostKeyboardFocus="TextBox_LostKeyboardFocus" GotKeyboardFocus="TextBox_GotKeyboardFocus" KeyUp="TextBox_KeyUp" VerticalAlignment="Top" Width="342" Visibility="visible"/>
- <TextBox x:Name="TB3" HorizontalAlignment="Left" Height="23" Margin="894,46,0,0" TextWrapping="Wrap" Text="Ersetzen durch" LostKeyboardFocus="TextBox_LostKeyboardFocus" GotKeyboardFocus="TextBox_GotKeyboardFocus" KeyUp="TextBox_KeyUp" VerticalAlignment="Top" Width="342" Visibility="visible"/>
- <RadioButton x:Name="RB1" Content="Ausgangstext" GroupName="1" HorizontalAlignment="Left" Margin="790,34,0,0" VerticalAlignment="Top" Visibility="visible"/>
- <RadioButton x:Name="RB2" Content="Zieltext" GroupName="1" HorizontalAlignment="Left" Margin="790,54,0,0" VerticalAlignment="Top" Visibility="visible"/>
- <RadioButton x:Name="RB3" Content="Text automatisch ersetzen" GroupName="2" HorizontalAlignment="Left" Margin="10,8,0,0" VerticalAlignment="Top"/>
- <RadioButton x:Name="RB4" Content="Segmente suchen" GroupName="2" HorizontalAlignment="Left" Margin="10,30,0,0" VerticalAlignment="Top"/>
- <!--<CheckBox x:Name="CB4" Content="Regex (C# .NET Core)" HorizontalAlignment="Left" Margin="1260,10,0,0" VerticalAlignment="Top" Visibility="visible"/>-->
- <!--<CheckBox x:Name="CB5" Content="Groß-/Kleinschreibung" HorizontalAlignment="Left" Margin="1260,33,0,0" VerticalAlignment="Top" Visibility="visible"/>-->
- <!--<CheckBox x:Name="CB6" Content="Ganze Wörter" HorizontalAlignment="Left" Margin="1260,56,0,0" VerticalAlignment="Top" Visibility="visible"/>-->
- <CheckBox x:Name="CB1" Content="Regex (C# .NET Core)" HorizontalAlignment="Left" Margin="540,8,0,0" VerticalAlignment="Top" Visibility="Hidden"/>
- <CheckBox x:Name="CB2" Content="Groß-/Kleinschreibung" HorizontalAlignment="Left" Margin="540,31,0,0" VerticalAlignment="Top" Visibility="visible"/>
- <CheckBox x:Name="CB3" Content="Ganze Wörter" HorizontalAlignment="Left" Margin="540,54,0,0" VerticalAlignment="Top" Visibility="visible"/>
- <Label x:Name="Lbl1" Content="Ersetzen in:" HorizontalAlignment="Left" Margin="787,3,0,0" VerticalAlignment="Top" Visibility="visible"/>
- <Label x:Name="Lbl2" Content="Zeilen/Seite" HorizontalAlignment="Left" Margin="703,3,0,0" VerticalAlignment="Top" Visibility="visible"/>
- <ComboBox x:Name="CoB1" HorizontalAlignment="Left" Margin="707,36,0,0" VerticalAlignment="Top" Width="50" Visibility="visible">
- <ComboBoxItem>10</ComboBoxItem>
- <ComboBoxItem IsSelected="True">25</ComboBoxItem>
- <ComboBoxItem>50</ComboBoxItem>
- <ComboBoxItem>75</ComboBoxItem>
- <ComboBoxItem>100</ComboBoxItem>
- <ComboBoxItem>250</ComboBoxItem>
- <ComboBoxItem>500</ComboBoxItem>
- <ComboBoxItem>750</ComboBoxItem>
- <ComboBoxItem>1000</ComboBoxItem>
- <ComboBoxItem>Alle</ComboBoxItem>
- </ComboBox>
- <Separator Height="100" Margin="0,34,0,0" VerticalAlignment="Top"/>
- <Grid Margin="419,90,386,95" HorizontalAlignment="Center" Width="600" >
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto">
- </ColumnDefinition>
- <ColumnDefinition Width="100"/>
- <ColumnDefinition Width="100">
- </ColumnDefinition>
- <ColumnDefinition Width="100">
- </ColumnDefinition>
- <ColumnDefinition Width="100"/>
- <ColumnDefinition Width="100"/>
- <ColumnDefinition Width="100">
- </ColumnDefinition>
- </Grid.ColumnDefinitions>
- <Button x:Name="Btn_erst" Grid.Column="1" Content="|<<" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="76" Visibility="visible" Height="20"/>
- <Button x:Name="Btn_zur" Grid.Column="2" Content="<" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="76" Visibility="visible" Height="20"/>
- <TextBox x:Name="TB4" Grid.Column="3" HorizontalAlignment="right" Height="23" Margin="0,0,0,0" BorderThickness="1" TextAlignment="Center" Text="x" VerticalAlignment="Top" Width="50" Visibility="visible" />
- <Label x:Name="Lbl3" Grid.Column="4" Content="von x" HorizontalAlignment="left" Margin="0,-3,0,0" VerticalAlignment="Top" Visibility="visible" Width="50" HorizontalContentAlignment="Center" Height="24"/>
- <Button x:Name="Btn_weiter" Grid.Column="5" Content=">" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="76" Visibility="visible" Height="20"/>
- <Button x:Name="Btn_letzte" Grid.Column="6" Content=">>|" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="76" RenderTransformOrigin="4.054,0.197" Visibility="visible" Height="20"/>
- </Grid>
- <ComboBox x:Name="CoB2" HorizontalAlignment="Left" Margin="1256,20,0,0" VerticalAlignment="Top" Width="120" Visibility="Hidden" />
- <Button x:Name="Btn_send" Content="Abschicken" HorizontalAlignment="Left" Margin="1256,58,0,0" VerticalAlignment="Top" Width="75" Visibility="Visible" RenderTransformOrigin="-0.646,1.173" />
- <Label x:Name="Lbl4" Content="Sprache wählen:" HorizontalAlignment="Left" Margin="1256,-6,0,0" VerticalAlignment="Top" Width="120" Visibility="Hidden"/>
- </Grid>
- </Window>
codebehind:
Helper:
VB.NET-Quellcode
- Public Class RichTextBoxHelper
- Inherits RichTextBox
- Private Shared _keytoken As String
- Public Property keytoken As String
- Get
- Return _keytoken
- End Get
- Set(ByVal value As String)
- _keytoken = value
- End Set
- End Property
- Public Property TextValue As String
- Get
- Return CStr(GetValue(TextValueProperty))
- End Get
- Set(ByVal value As String)
- SetValue(TextValueProperty, value)
- End Set
- End Property
- Public Shared ReadOnly TextValueProperty As DependencyProperty = DependencyProperty.Register("TextValue", GetType(String), GetType(RichTextBoxHelper), New FrameworkPropertyMetadata("", New PropertyChangedCallback(AddressOf FinalValueChanged)))
- Private Shared Sub FinalValueChanged(ByVal obj As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
- Dim newvalue As String = CStr(e.NewValue)
- Dim textBox As RichTextBox = CType(obj, RichTextBox)
- If e.NewValue IsNot Nothing Then
- textBox.Document.Blocks.Clear()
- textBox.Document.Blocks.Add(New Paragraph(New Run(e.NewValue.ToString())))
- Dim wordRanges As IEnumerable(Of TextRange) = GetAllWordRanges(textBox.Document)
- For x = 1 To count
- Dim numberpattern As String = "{t" & x & "}"
- matches = Regex.Matches(textBox.Document.ToString, numberpattern)
- For Each wordRange As TextRange In wordRanges
- If _keytoken IsNot Nothing Then
- If wordRange.Text = "{t" & x & "}" Then
- 'wordRange.Text = ""
- wordRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Purple)
- wordRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold)
- End If
- If wordRange.Text = "{s" & x & "}" Then
- If (dic_suche.ContainsKey("{s" & x & "}")) Then
- str_tag = dic_suche.Item("{s" & x & "}")
- End If
- wordRange.Text = str_tag
- wordRange.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red)
- wordRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold)
- 'wordRange.ClearAllProperties()
- End If
- End If
- Next
- Next
- End If
- End Sub
- Public Shared Iterator Function GetAllWordRanges(ByVal document As FlowDocument) As IEnumerable(Of TextRange)
- Dim numberpattern As String = "{(s|t)\d+}"
- Dim pointer As TextPointer = document.ContentStart
- While pointer IsNot Nothing
- If pointer.GetPointerContext(LogicalDirection.Forward) = TextPointerContext.Text Then
- Dim textRun As String = pointer.GetTextInRun(LogicalDirection.Forward)
- Dim matches As MatchCollection = Regex.Matches(textRun, numberpattern)
- For Each match As Match In matches
- 'dic_result.Add(match.ToString, "{te}")
- Dim startIndex As Integer = match.Index
- Dim length As Integer = match.Length
- Dim start As TextPointer = pointer.GetPositionAtOffset(startIndex)
- Dim [end] As TextPointer = start.GetPositionAtOffset(length)
- Yield New TextRange(start, [end])
- Next
- End If
- pointer = pointer.GetNextContextPosition(LogicalDirection.Forward)
- End While
- End Function
- Public Shared Function GetText(ByVal document As FlowDocument) As String
- Return New TextRange(document.ContentStart, document.ContentEnd).Text
- End Function
- End Class
Befüllen des Datagrids über DataTable:
Solltet Ihr noch etwas zusätzlichen Code zum besseren Nachvollziehen benötigen, bitte melden.
LG,
Pascal
Leider hab ich nicht immer Zeit zum Programmieren, da es eher ein Hobby ist. Falls ich mal im Forum ne Frage stelle und länger nicht antworte, nicht böse sein: Ich bin dann entweder beruflich oder mit der Familie zu sehr eingespannt oder einfach zu müde. Das kann erfahrungsgemäß auch mal über Wochen dauern, aber ich melde mich immer und setze die Frage ggf. auf beantwortet.