Get und Set einer RTB (xceed) bei Änderung auslösen?

  • WPF

Es gibt 31 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

    Hallo Sascha (@'Nofear23m'),

    So, hab gestern mal wieder etwas Ziet gehabt und die OC wieder wie folgt eingebunden (auskommentiert):

    XAML:

    XML-Quellcode

    1. <DataGridTextColumn Header="Id" Binding="{Binding URID}" Width="Auto"></DataGridTextColumn>
    2. <DataGridTemplateColumn Header="source_segment" Width="50*">
    3. <DataGridTemplateColumn.CellTemplate>
    4. <DataTemplate>
    5. <toolkit:RichTextBox
    6. x:Name="rtb" VerticalScrollBarVisibility="Auto" Text="{Binding SOURCE,
    7. Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
    8. <myCustomFormatter:MyFormatter />
    9. </toolkit:RichTextBox.TextFormatter>-->
    10. <toolkit:RichTextBox.TextFormatter>
    11. <toolkit:PlainTextFormatter />
    12. </toolkit:RichTextBox.TextFormatter>
    13. </toolkit:RichTextBox>
    14. </local:RichTextBoxHelper>-->
    15. </DataTemplate>
    16. </DataGridTemplateColumn.CellTemplate>
    17. <DataGridTemplateColumn.CellStyle>
    18. <Style>
    19. <Setter Property="TextBlock.TextWrapping" Value="Wrap" />
    20. </Style>
    21. </DataGridTemplateColumn.CellStyle>
    22. </DataGridTemplateColumn>
    23. <DataGridTemplateColumn Header="target_segment" Width="50*">
    24. <DataGridTemplateColumn.CellTemplate>
    25. <DataTemplate>
    26. <toolkit:RichTextBox
    27. x:Name="rtb" VerticalScrollBarVisibility="Auto" Text="{Binding TARGET,
    28. Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
    29. <toolkit:RichTextBox.TextFormatter>
    30. <toolkit:PlainTextFormatter />
    31. </toolkit:RichTextBox.TextFormatter>
    32. </toolkit:RichTextBox>
    33. </local:RichTextBoxHelper>-->
    34. </DataTemplate>
    35. </DataGridTemplateColumn.CellTemplate>


    Code behind:

    VB.NET-Quellcode

    1. Public oc As New ObservableCollection(Of Pair)


    VB.NET-Quellcode

    1. Public Class Pair
    2. #Region "Properties"
    3. Private id As String
    4. Private source_segment As String
    5. Private target_segment As String
    6. #End Region
    7. Public Property URID() As String
    8. Get
    9. Return id
    10. End Get
    11. Set(ByVal value As String)
    12. id = value
    13. End Set
    14. End Property
    15. Public Property SOURCE() As String
    16. Get
    17. Return source_segment
    18. End Get
    19. Set(ByVal value As String)
    20. source_segment = value
    21. End Set
    22. End Property
    23. Public Property TARGET() As String
    24. Get
    25. Return target_segment
    26. End Get
    27. Set(ByVal value As String)
    28. target_segment = value
    29. End Set
    30. End Property
    31. End Class


    Befüllt über:

    VB.NET-Quellcode

    1. Dim PAAR As New Pair
    2. PAAR = New Pair
    3. PAAR.URID = str_id.ToString
    4. PAAR.SOURCE = str_source.ToString
    5. PAAR.TARGET = str_target.ToString
    6. oc.Add(PAAR)



    Bindung:

    VB.NET-Quellcode

    1. DG1.ItemsSource = oc.AsEnumerable


    AsEnumerable, deshalb weil ich später ein Paging einbauen möchte.

    Passt das so, oder kann/sollte man das noch optimieren?

    Get und Set für die RTBs hab ich noch nichts vorangebracht, aber bin noch dran.

    LG,
    Pascal

    *CodeTags korrigiert* ~NoFear23m
    :!: 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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Nofear23m“ ()

    Hallo Pascal

    Das sieht ja schon mal gut aus. Das ist nun der WPF like Weg.

    Translating-IT schrieb:

    AsEnumerable, deshalb weil ich später ein Paging einbauen möchte

    Muss nicht sein. Die ObservableCollection erbt von Collection(Of T) und Collection(Of T) implementiert wiederum IEnumerable(Of T).
    Du kannst auch auf die ObservableCollection Take und Skip anwenden.

    VB.NET-Quellcode

    1. DG1.ItemSource = oc.Skip(10).Take(10)


    Translating-IT schrieb:

    Passt das so, oder kann/sollte man das noch optimieren?

    Nichts grawierendes. Du wirst es im Moment nicht benötigen aber wenn du später mal die Properties veränderst und möchtes das die Werte im View aktualisiert werden sollte INotifyPropertyChanged in die "Pair" Klasse implementiert werden und im Setter jedes Properties das Event OnPropertyChanged geworfen werden. Aber wenn es nicht benötigt wird ist es (noch) nicht nötig.

    Hier:

    VB.NET-Quellcode

    1. Dim PAAR As New Pair
    2. PAAR = New Pair
    3. PAAR.URID = str_id.ToString
    4. PAAR.SOURCE = str_source.ToString
    5. PAAR.TARGET = str_target.ToString
    6. oc.Add(PAAR)

    Brauchst du die Variable nicht zweimal instanziieren. PAAR = New Pair kann man weglassen denn das machst du ja mit Dim PAAR as [b]New[/b] Pair

    Das ganze könnte man mit einer überladung des Kostruktors verweinfachen oder wie folgt instanziieren:

    VB.NET-Quellcode

    1. oc.Add(New Pair() With {.URID = str_id.ToString, .SOURCE = str_source.ToString, .TARGET = str_target.ToString})



    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo Sascha,

    Quellcode

    1. Du kannst auch auf die ObservableCollection Take und Skip anwenden.


    Ah, ok. Gut zu wissen.

    Quellcode

    1. Du wirst es im Moment nicht benötigen aber wenn du später mal die Properties veränderst und möchtes das die Werte im View aktualisiert werden sollte INotifyPropertyChanged in die "Pair" Klasse implementiert werden und im Setter jedes Properties das Event OnPropertyChanged geworfen werden. Aber wenn es nicht benötigt wird ist es (noch) nicht nötig.

    Da in diesem Projekt nichts derartiges geplant ist, kann ich es weglassen. Das Einzige, was ich noch brauch ist die Formatierung der RTB-Texte beim ersten Befüllen. Und da brauch ich OnPropertyChanged nicht, oder? Danach wird nur noch per UI was geändert.

    Quellcode

    1. Brauchst du die Variable nicht zweimal instanziieren.


    Stimmt, habe ich übersehen.

    Quellcode

    1. Das ganze könnte man mit einer überladung des Kostruktors verweinfachen oder wie folgt instanziieren:


    Ist noch besser … 4 Zeilen Code weniger.

    Aber an dem depperten Get u. Set für die RTBs verzweifle ich.
    Ich check nicht mal, was ich, ausgehend vom XAML aus Post 21, "Implent"ieren muss um darauf zuzugreifen, ITextFormatter, oder was anderes? Mit was fange ich an?

    Quellcode

    1. Implements ITextFormatter
    2. Public Function GetText(ByVal document As FlowDocument) As String Implements ITextFormatter.GetText
    3. Dim tr As TextRange = New TextRange(document.ContentStart, document.ContentEnd)
    4. Using ms As MemoryStream = New MemoryStream()
    5. tr.Save(ms, DataFormats.Rtf)
    6. Return ASCIIEncoding.[Default].GetString(ms.ToArray())
    7. End Using
    8. End Function
    9. Public Sub SetText(ByVal document As FlowDocument, ByVal text As String) Implements ITextFormatter.SetText
    10. Try
    11. If String.IsNullOrEmpty(text) Then
    12. document.Blocks.Clear()
    13. Else
    14. Dim tr As TextRange = New TextRange(document.ContentStart, document.ContentEnd)
    15. Using ms As MemoryStream = New MemoryStream(Encoding.ASCII.GetBytes(text))
    16. tr.Load(ms, DataFormats.Rtf)
    17. End Using
    18. End If
    19. Catch
    20. Throw New InvalidDataException("Data provided is not in the correct RTF format.")
    21. End Try
    22. End Sub


    Ist das annähernd richtig, oder bin ich völlig auf dem Holzweg?

    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.
    Hallo Sascha @Nofear23m,

    Ich geb's auf. Ich krieg dieses sch… get und set für die RTBs einfach nicht hin.

    Kann ich die Texte beim Befüllen vom OC eigentlich irgendwie so "vorformatieren", dass die Texte gleich fett oder farbig in die RTBs geladen und entsprechend formatiert angezeigt werden? Dann bräuchte ich Get und Set hier nicht mehr.

    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.
    Hallo

    Sorry das ich nicht gleich Antworten kann/konnte, ich habe im Moment viel stress in der Arbeit. Ich wollte dir ein Beispiel erstellen, komme aber erst gegen Wochenende dazu.
    Ich weis was du meinst mit befüllen. Das geht natürlich auch, du kannst ja den zu übergebenen Text vorher quasi umformatieren, das ist aber ne doofe Arbeit und sicher mühseelig.

    Ich kann dir gerne (ich denke Freitag würde ich dazu kommen) ein kleines Beispiel machen, hier wäre Hilfreich ein paar Beispieltexte zu haben.
    Also ein paar Datensätze von deinen Rohdaten und jeweils das was am Ende rauskommen soll. Also den formatierten Part.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Hallo Sascha,

    Kein Problem. Ist bei mir ja auch oft nicht anders.

    Ich hab mir die Beispiele zu Get und Set im Binding-Video angeschaut und auch so noch recherchiert, aber irgendwas scheine ich falsch zu machen. Das Get scheint nicht mal zu funktionieren.

    An sich sind die zu formatierenden Texte immer laut gleichem Schema. Über Get und Set würde ich es ja auch nur automatisiert umformatieren lassen. Meiner Meinung nach, macht es dann keinen Unterschied, ob ich es beim Get/Set per Formatierung der Paragraphen nach der Erstbefüllung mache, oder schon vorher. Ist nur einmal zu programmieren. Aber dass ich das Get/Set für die RTBs nicht hinbekomme, ärgert mich schon etwas.

    Die Ersetzungen habe ich vor der xceed-Version immer mit Regex-Match durchgeführt. Hat auch ganz gut geklappt.


    Da sich die Texte im Allgemeinen ändern und nur die zu formatierenden Teile gleich bleiben, ist ein Beispieltext recht einfach. Weitere Texte können nach Belieben generiert werden, indem weitere {t\d}- bzw. {s\d}-Platzhalter eingefügt bzw. generiert werden.


    Ausgangstext: {t1}Das ist ein Beispieltext{t2} mit unterschiedlicher Formatierung {s1}.

    Gewünschtes Format: {t1}Das ist ein Beispieltext{t2} mit unterschiedlicher Formatierung {s1}.


    {t\d} soll immer Fettschrift und violett sein, {s\d} immer Fettschrift und rot.

    Reicht das Beispiel oder brauchst Du mehr Text(e)?

    Ursprünglich wollte ich die {t\d} durch ein violettes Tag wie im nachfolgenden Beispiel ersetzen, aber das scheint laut meinen Recherchen in einer RTB noch schwieriger, wäre aber optisch etwas schöner, aber Violett und Fett passt auch ganz gut.

    Beispiel:

    oder halt ein rechteckiges oder wabenförmiges Tag.

    LG,
    Pascal
    Bilder
    • anni-tanni-tags-raw-doc.jpg

      53,04 kB, 655×294, 65 mal angesehen
    :!: 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.

    Neu

    Hallo Pascal

    Ich habe mal ein kleine Beispiel erstellt da ich huete kurz Zeit hatte.

    Schau dir das mal an, ist evtl. nicht genau die Formattierung die du benötigst, aber anpassen ist ja einfach. Im Grunde ja nur eine spielerei.
    Ich habe die Formatierung nun so gestalltet das es immer auch einen CloseTag gibt. Also {ts} eröffnet den Tag und {\ts} schliesst diesen wieder. Aber wie gesagt, anpassen ist ja einfach.

    Ich denke damit solltest du nun dein Problem soweit lösen können denke ich.

    PS: Das zurückformatieren habe ich jetzt nicht vollständig implementiert, aber beim ersten Formatter habe ich dir zumindest ein Beispiel reingepackt wie es funktioniert.

    Grüße
    Sascha
    Bilder
    • Anmerkung 2019-07-13 154519.png

      23,31 kB, 709×440, 13 mal angesehen
    Dateien
    • WpfApp1.zip

      (1,51 MB, 4 mal heruntergeladen, zuletzt: )
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Neu

    Hallo Sascha,


    Danke, hab mir das Ganze mal angeschaut. Sehr interessantes Beispiel.

    Ich brauche im Endeffekt einen Kombination aus beiden Lösungsansätzen. Fettschrift für Rot und Tag für Violett. Aber das umzusetzen sollte in diesem Fall einfach sein, einfach das hernehmen, was ich jeweils benötige.

    Wie, über welche Zeile, kann ich das Tag verändern? Ich möchte versuchen, eine Wabe daraus zu machen.


    Ich habe auch versucht, die Daten in meine Lösung einzubinden, um dort mit der Datenstruktur und RTB-Einbindung weiterzuexperimentieren, die bei mir schon programmiert ist, aber ich erhalte 2 Fehlermeldungen:


    in der Haupt-XAML macht diese Zeile Probleme:

    Quellcode

    1. <rtbformatter:MySpecialFormatter/>



    Fehler:
    Der Name "MySpecialFormatter" ist im Namespace "clr-namespace:TMEdit.RtbFormatter" nicht vorhanden.

    Aber sie ist vorhanden.

    Eine Schnellaktion oder Refactoring wird nicht angeboten.

    Edit: obigen Fehler habe ich nun nach mehreren Versuchen durch eine erzwungene Neuerstellung der Projektmappe lösen können.


    In der Datei MySpecialIconFormatter

    schimpft VS, dass .Angle und .text jeweils kein Member von ucITs sind, aber sie sind doch in der entsprechenden XAML vorhanden.

    Auch hier wird wiederum weder Schnellaktion noch Refactoring angeboten.


    Grüße,
    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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Translating-IT“ ()

    Neu

    Translating-IT schrieb:

    schimpft VS, dass .Angle und .text jeweils kein Member von ucITs sind, aber sie sind doch in der entsprechenden XAML vorhanden.

    Das ist der Grund warum ich immer Empfehle eigene Lösungen anhand der "Vorlage" zu implementieren. Mit Copy&Paste vergisst man schnell mal was. Dem UserControl habe ich nämlich genau diese Eigenschaften als DependencyProperties spendiert und im XAML dann schlicht darauf gebunden. Somit findet man diese nicht im XAML sondern in der CodeBehind. Bez. DependencyProperties verweise ich wiedermal auf meine Tutorialreihe.

    Wenn du eine Wabe daraus machen willst musst du nur das Usercontrol entsprechend verändern.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Neu

    na super … die einzige Datei, bei der ich komplett übersehen habe, die Codebehind anzuschauen … Bei allen anderen habe ich daran gedacht. *grml*

    Ich glaube es liegt daran, dass bei den anderen nichts im Codebehind war und deshalb hab ich da nimmer dran gedacht zu schauen.



    Dann werd ich mal weiter rumexperimentieren und schauen, ob noch was Problemchen bereitet. Aber ich glaube es sollte kein großes Problem sein.

    Auch den Get und Set nehme ich mir nochmal genauer unter die Lupe.

    Edit:

    Von den Formatierungen her schaut es schon ganz gut aus. Ich habe beide Formatter in einem Namespace kombiniert.

    Es gibt nur ein kleines Problem: die roten Texte in Fettschrift dienen dazu, dem Kunden zu zeigen, wo er was ändern kann/soll (also die rot formatierten Texte). Bei einigen Segmenten funktioniert das Ersetzen ohne Probleme, bei anderen wird folgende Fehlermeldung ausgeworfen:

    Nachricht = Das Objekt des Typs "System.Windows.Documents.InlineUIContainer" kann nicht in Typ "System.Windows.Documents.Run" umgewandelt werden.

    Bei diesem Test passiert es in jeder 2. "Tabellen"-Zeile. Kann auch nur ein Zufall sein, dass es in jeder 2. auftritt. Ich habe noch keine Zeit gehabt mir das genauer bzw. mit anderen Testdaten anzuschauen, da es schon recht spät ist, aber vielleicht fällt Dir ja auf Anhieb was dazu ein. Ein Verdacht von mir fällt darauf, dass es nur in Zellen auftritt, in denen beide Formatierungen (also tp und ts) vorhanden sind. Muss ich mir dann morgen oder so noch genauer anschauen.


    Die Änderung am UserControl habe ich noch nicht ganz raus, mir fehlen grad die Referenzpunkte zum Zeichnen. Erinnert mich irgendwie an PC Logo aus den 90ern. Gibt es nur die Möglichkeit die Linien programmatisch zu ziehen oder kann man die auch irgendwie "zeichnen"?

    Die Rückformatierung am Ende ist auch kein Problem in diesem Usecase. Ich rufe die Werte aus den Zellen im Codebehind über die OC ab und dort sind die Formatierungen nicht vorhanden. Nur die ursprünglichen Tags.

    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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Translating-IT“ ()

    Neu

    Hallo,

    Der Fehler tritt in jedem Feld auf, das ein UserControl TP enthält. Unabhängig von dessen Position. Eigentlich sollte der Case Else den Text davor und danach in Run umwandeln (oder nicht?), aber das scheint nicht zu geschehen, und falls es doch geschieht, dann behält der InlineUIContainer die Kontrolle über das gesamte Feld.

    Grüße,
    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.

    Neu

    Translating-IT schrieb:

    wird folgende Fehlermeldung ausgeworfen

    Der InlineUIContainer ist wie der Name sagt wirklich nur da um UI, also Controls in eine RTB einzufügen. So wie ich es mit dem UserControl mache.
    Run ist nur Text, dafür benötigt es keinen InlineUIContainer. Schau dir mal auf MSDN die RTB genauer an und versuche zu lernen wie die RTB und deren Content aufgebaut werden muss/soll. Dann tust du dir gleich um einiges leichter.

    Translating-IT schrieb:

    Gibt es nur die Möglichkeit die Linien programmatisch zu ziehen oder kann man die auch irgendwie "zeichnen"?

    Sicher, es gibt Grafik-Programme welche direkt in XAML exportieren können. XAML ist ja Vektorbeasiert. Wenn du allerdings nicht mit den Path's arbeiten willst kannst du auch ein Image-Control verwenden.

    Ich kann dir bei deinem aktuellen problem nicht weiterhalfen ohne Code. Wenn du ein Problem mit einer Fehlermeldung hast ist es immer Hilfreich wenn du den relevanten Code postest, ich kann ja leider nicht wissen wie der aktuelle Stand ist und wo der Fehler auftritt. Wie gesagt musst du aber unbedingt versuchen zu verstehen was hier genau passiert und wie der Inhalt einer RTB aufgebaut ist. Nur so wirst du die Formatierung nach deinen wünschen anpassen können - und vor allem kann hier auch in sachen performance viel herausgeholt werden wenn man weis wie man die RTB aufbaut.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##