WPF-Alternative zur FastColoredTextbox

  • VB.NET

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

    Neu

    BindingMode=TwoWay?

    Klappt das nicht? Ich kanns gerade nich probieren.
    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

    Hab ich schon eingestellt, funktioniert aber auch nicht.

    Wenn man sich überlegt: Wie soll denn überhaupt dieses Attaced Property etwas von der Änderung mitbekommen. Es ist ja nicht mit dem Text Property verbunden (dieses unterstützt ja kein Binding).
    Das einzige was das Attaced Property macht ist den Text bei Wertveränderung SETZEN.

    So sehe ich das mit meinem Kenntnisstand. Kläre mich ruhig auf, wenn ich einen Denkfehler drinne habe.

    Viele Grüße
    Florian

    Neu

    Aber von meiner Logik her schon. Muss aber natürlich bei beiden gesetzt werden. Also bei beiden RTBs.

    Aber gerne probier ichs morgen mal aus.

    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

    Huhu,
    ist ja witzig das 3 Leute gleichzeit ähnliche Programme machen :)
    Ich bin nebenher dabei, mein SnippsCode Programm von WinForms auf WPF umzustellen.
    Anders als bei dem WinForms Programm möchte ich beim neuen Programm mit Dateien arbeiten, nicht mit einem Datatset...
    Daher sind meine Anforderungen an AvalonEdit etwas einfacher....
    Ich habe in meinem ViewModel einfach eine neue TextEditor Instanc generiert, stelle dort die Properties ein. Im Xaml habe ich dann ein ContentControl welches ich an die TextEditor Instanz des ViewModel binde.
    Klappt super...

    XML-Quellcode

    1. <Grid>
    2. <TabControl>
    3. <TabItem>
    4. <ContentControl Content="{Binding CodeEditor}"/>
    5. </TabItem>
    6. </TabControl>
    7. </Grid>


    Das ViewModel:

    C#-Quellcode

    1. using MHoApps.Core.ViewModel;
    2. using ICSharpCode.AvalonEdit;
    3. using ICSharpCode.AvalonEdit.Highlighting;
    4. using ICSharpCode.AvalonEdit.Document;
    5. using System.IO;
    6. namespace MHoApps.SnippsCode.ViewModel
    7. {
    8. /// <summary>
    9. ///
    10. /// </summary>
    11. public class EditorViewModel : ViewModelBase
    12. {
    13. #region Private Properties
    14. private readonly TextEditor _codeEditor = new TextEditor();
    15. #endregion
    16. #region Constructor
    17. /// <summary>
    18. /// default constructor
    19. /// </summary>
    20. public EditorViewModel()
    21. {
    22. _codeEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(File)); ;
    23. _codeEditor.ShowLineNumbers = ShowLineNumbers;
    24. _codeEditor.Load(File);
    25. }
    26. #endregion
    27. #region Public Properties
    28. public string File { get; set; } = @"D:\AzureDevOps\MHoApps\Special\WindowViewModel.cs";
    29. public TextEditor CodeEditor => _codeEditor;
    30. public string SyntaxHighlighting { get; set; }
    31. public bool ShowLineNumbers { get; set; } = true;
    32. public string EditorText { get; set; }
    33. #endregion
    34. }
    35. }


    Das schöne daran ist, das AvalonEdit das SyntaxHighlighting anhand der File Extension erledigen kann...
    "Hier könnte Ihre Werbung stehen..."

    Neu

    JA, ist mir auch schon aufgefallen. Ich sehe nur noch RTBs. :P

    MichaHo schrieb:

    Ich habe in meinem ViewModel einfach eine neue TextEditor Instanc generiert,

    Uhhhh. :S Ab hier ist es dann im Grunde kein ViewModel mehr. Entweder CodeBehind oder MVVM. Hier holst du dir die View ins ViewModel.

    Geht auch ohne, wie du gesehen hast kannst du ja ein AttachedPRoperty erstellen auf welches du Bindenkannst oder du erstellst dir ein UserControl und in deren CodeBehind reagierst du auf das Ereignis "DataContext_Changed" und holst dir das ViewModel in die CodeBehind und füllst die Avalon RTB. Fertich.

    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

    Hi @Nofear23m jepp, so ist der Plan... (also ein UserControl) bin noch am testen wegen dem öffnen und speichern von files, daher erstmal das AvalonEdit im ViewModel.

    Bin gerade noch dabei zu erörtern, wie ich mehrere TabItems bzw. TabControls neben einander anzeige... hast Du da vielleicht ein einfaches Beispiel?
    "Hier könnte Ihre Werbung stehen..."

    Neu

    MichaHo schrieb:

    wie ich mehrere TabItems bzw. TabControls neben einander anzeige

    Das musst du genauer eklären, aber besser in einem neuen Thread. ;)
    Denn.... die sind ja nebeneinander.

    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

    Hallo,

    so ich habe mein Problem (mit dem Text Binding an den AvalonTextEditor) so weit gelöst. Allerdings bin ich mir sicher, dass das nicht ganz "WPFlike" ist:

    Im XAML setze ich jetzt einfach einen EventHandler auf das TextChanged Event, siehe:

    XML-Quellcode

    1. <Window x:Class="AvalonTextEditBindingHelper.MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:local="clr-namespace:AvalonTextEditBindingHelper"
    7. xmlns:avalon="http://icsharpcode.net/sharpdevelop/avalonedit"
    8. xmlns:vm="clr-namespace:AvalonTextEditBindingHelper"
    9. mc:Ignorable="d"
    10. Title="MainWindow" Height="450" Width="800">
    11. <Window.DataContext>
    12. <vm:MainViewModel/>
    13. </Window.DataContext>
    14. <Grid>
    15. <Grid.RowDefinitions>
    16. <RowDefinition Height="*"/>
    17. <RowDefinition Height="*"/>
    18. </Grid.RowDefinitions>
    19. <avalon:TextEditor vm:AvalonTextBindingHelper.AvalonText="{Binding Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" SyntaxHighlighting="C#"
    20. TextChanged="TextEditor_TextChanged">
    21. </avalon:TextEditor>
    22. <TextBox Grid.Row="1" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
    23. </TextBox>
    24. </Grid>
    25. </Window>


    Im CodeBehind fange ich dieses Event ab, und verarbeite es so:

    C#-Quellcode

    1. private void TextEditor_TextChanged(object sender, EventArgs e)
    2. {
    3. TextEditor t = (TextEditor)sender;
    4. AvalonTextBindingHelper.SetAvalonText(t, t.Text);
    5. }


    Die AvalonTextBindingHelper Klasse und das MainViewModel ist gleich wie im vorherigen Post, trozdem zur Übersicht hier noch einmal:

    MainViewModel

    C#-Quellcode

    1. public class MainViewModel : ViewModelBase
    2. {
    3. private string _Text;
    4. public string Text
    5. {
    6. get { return _Text; }
    7. set { _Text = value; RaisePropertyChanged(); }
    8. }
    9. public MainViewModel()
    10. {
    11. Text = "public in i = 0;";
    12. }
    13. }


    AvalonTextBindingHelper

    C#-Quellcode

    1. public class AvalonTextBindingHelper
    2. {
    3. public static string GetAvalonText(TextEditor obj)
    4. {
    5. return (string)obj.GetValue(AvalonTextProperty);
    6. }
    7. public static void SetAvalonText(TextEditor obj, string value)
    8. {
    9. obj.SetValue(AvalonTextProperty, value);
    10. }
    11. // Using a DependencyProperty as the backing store for AvalonText. This enables animation, styling, binding, etc...
    12. public static readonly DependencyProperty AvalonTextProperty =
    13. DependencyProperty.RegisterAttached("AvalonText", typeof(string), typeof(AvalonTextBindingHelper), new PropertyMetadata("", AvalonTextProperty_Changed));
    14. private static void AvalonTextProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
    15. {
    16. TextEditor textEditor = (TextEditor)d;
    17. textEditor.Document.Text = e.NewValue.ToString();
    18. }
    19. }



    @Nofear23m Eventuell könntest du mir noch eine WPF konforme Lösung aufzeigen, wenn es da eine gibt.

    Viele Grüße
    Florian

    Neu

    Hallo Florian

    Eine möglichkeit wäre im Grunde genau das was du über die CodeBehind gemacht hast in den Helper zu packen. Das hätte den Vorteil das es dort wiederverwendbar ist und somit immer funktioniert ohne das man daran denken muss in die CodeBehind was einzufügen.

    VB.NET-Quellcode

    1. Imports ICSharpCode.AvalonEdit
    2. Namespace XamlHeper
    3. Public Class AvalonTextBindingHelper
    4. Inherits DependencyObject
    5. Public Shared Function GetAvalonText(ByVal element As DependencyObject) As String
    6. If element Is Nothing Then
    7. Throw New ArgumentNullException("element")
    8. End If
    9. Return CType(element.GetValue(AvalonTextProperty), String)
    10. End Function
    11. Public Shared Sub SetAvalonText(ByVal element As DependencyObject, ByVal value As String)
    12. If element Is Nothing Then
    13. Throw New ArgumentNullException("element")
    14. End If
    15. element.SetValue(AvalonTextProperty, value)
    16. End Sub
    17. Public Shared ReadOnly AvalonTextProperty As _
    18. DependencyProperty = DependencyProperty.RegisterAttached("AvalonText",
    19. GetType(String), GetType(AvalonTextBindingHelper),
    20. New PropertyMetadata(Nothing, AddressOf AvalonTextProprty_Changed))
    21. Private Shared Sub AvalonTextProprty_Changed(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
    22. Dim textEditor As TextEditor = CType(d, TextEditor)
    23. RemoveHandler textEditor.TextChanged, AddressOf AvalonText_Changed
    24. AddHandler textEditor.TextChanged, AddressOf AvalonText_Changed
    25. textEditor.Document.Text = e.NewValue.ToString
    26. End Sub
    27. Private Shared Sub AvalonText_Changed(ByVal sender As Object, ByVal e As EventArgs)
    28. Dim av = DirectCast(sender, TextEditor)
    29. av.SetValue(AvalonTextProperty, av.Document.Text)
    30. End Sub
    31. End Class
    32. End Namespace


    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6. xmlns:avalon="http://icsharpcode.net/sharpdevelop/avalonedit"
    7. xmlns:local="clr-namespace:AvalonDemo"
    8. xmlns:helper="clr-namespace:AvalonDemo.XamlHeper"
    9. mc:Ignorable="d"
    10. Title="MainWindow" Height="450" Width="800">
    11. <Window.DataContext>
    12. <local:DemoClass/>
    13. </Window.DataContext>
    14. <Grid>
    15. <Grid.RowDefinitions>
    16. <RowDefinition Height="*"/>
    17. <RowDefinition Height="*"/>
    18. </Grid.RowDefinitions>
    19. <avalon:TextEditor x:Name="myAvalon" ShowLineNumbers="True" helper:AvalonTextBindingHelper.AvalonText="{Binding MyTextPropInViewModel,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Grid.Row="0" Margin="5"/>
    20. <TextBox Text="{Binding MyTextPropInViewModel,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" x:Name="myTextBox" Grid.Row="1" Margin="5" TextWrapping="Wrap"/>
    21. </Grid>
    22. </Window>


    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

    Hallo

    Um sicher zu gehen das es nur einen einzigen gibt.

    Da der Handler ja immer bei jeder Textänderung aufgerufen wird würde er dann beim 3. Buchstaben die Prozedur bereits 3x ausführen, beim 10. Buchstaben bereits 10x. Ich denke ab dem 20. Buchstaben wirds dann sicher sehr langsam. ;)

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