Bessere Möglichkeit?

  • WPF

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von Runshak.

    Bessere Möglichkeit?

    Hallo,

    ich habe zwei Textboxen (WPF). Die eine nimmt die ip-Adresse auf, die andere die Portnummer. Dann speicher ich deren Inhalt in .txt-Dateien.

    C#-Quellcode

    1. public void OnSpeichern(object sender, RoutedEventArgs e)
    2. {
    3. Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
    4. dialog.Filter = "Txt-Files(*.txt)|*.txt";
    5. Nullable<bool> result = dialog.ShowDialog();
    6. if (result == true)
    7. {
    8. File.WriteAllText(dialog.FileName, hostNameFeld.Text);
    9. }
    10. Nullable<bool> result2 = dialog.ShowDialog();
    11. if (result2 == true)
    12. {
    13. File.WriteAllText(dialog.FileName, portnummerFeld.Text);
    14. }
    15. }


    das funktioniert auch wunderbar

    und dann wird das über

    C#-Quellcode

    1. public void OnLaden(object sender, RoutedEventArgs e)
    2. {
    3. Microsoft.Win32.OpenFileDialog dialogo = new Microsoft.Win32.OpenFileDialog();
    4. dialogo.Filter = "Txt-Files(*.txt)|*.txt";
    5. Nullable<bool> result = dialogo.ShowDialog();
    6. if (result == true)
    7. {
    8. hostNameFeld.Text = File.ReadAllText(dialogo.FileName);
    9. }
    10. Nullable<bool> result2 = dialogo.ShowDialog();
    11. if (result2 == true)
    12. {
    13. portnummerFeld.Text = File.ReadAllText(dialogo.FileName);
    14. }
    15. }


    wieder geladen...

    ich öffne in beiden Fällen immer zwei Dialogfenster. Im ersten wähle ich die ip-Adresse und im zweiten die Portnummer... gibt es da was hübsches "schöneres" oder ist das eurer Meinung nach so in Ordnung wie ich das habe...

    Verschoben. ~Thunderbolt

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

    Moin,

    das ist so auf keinen Fall richtig. :P
    In WPF verwendet man MVVM, Bindings und pro Window ein ViewModel, das ist da nicht wie in Windows Forms, da werden dann in Properties im ViewModel die Daten gespeichert und via Binding an das Control weitergeleitet, welches dann seinen Content anpassen kann, sobald es erfährt, dass etwas geändert wurde (INotifyPropertyChanged). Einfach mal etwas danach googlen, da sollte sich was finden.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Aber davon abgesehen: Warum sollte der Benutzer selbst auswählen wollen, wo er die Einstellungen speichert?
    Da würden sich die My.Settings anbieten. Oder was eigenes (z.B. Xml-Datei im AppData-Ordner).
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils
    So hab jetzt mein Projekt ein wenig überarbeitet...

    im XAML

    XML-Quellcode

    1. ​<MenuItem Header="Speichern"
    2. Command="{Binding Speichern}"/>


    im Codebehind

    C#-Quellcode

    1. public MainWindow()
    2. {
    3. InitializeComponent();
    4. this.DataContext = new HauptfensterStart();
    5. }


    weitere Klasse

    C#-Quellcode

    1. ​public partial class HauptfensterStart : Chilfe
    2. {
    3. public string ipAddress { get; set; }
    4. public string portNumber { get; set; }
    5. public ICommand Speichern
    6. {
    7. get { return new Cbefehl(OnSpeichern); }
    8. }
    9. public void OnSpeichern()
    10. {
    11. Microsoft.Win32.SaveFileDialog dialog = new Microsoft.Win32.SaveFileDialog();
    12. dialog.Filter = "Txt-Files(*.txt)|*.txt";
    13. Nullable<bool> result = dialog.ShowDialog();
    14. if (result == true)
    15. {
    16. File.WriteAllText(dialog.FileName, ipAddress);
    17. }
    18. Nullable<bool> result2 = dialog.ShowDialog();
    19. if (result2 == true)
    20. {
    21. File.WriteAllText(dialog.FileName, portNumber);
    22. }
    23. }
    24. }


    Hilfsklasse

    C#-Quellcode

    1. ​{
    2. public abstract class Chilfe : INotifyPropertyChanged
    3. {
    4. private Dictionary<string, object> _values = new Dictionary<string, object>();
    5. public event PropertyChangedEventHandler PropertyChanged;
    6. public void NotifyPropertyChanged(string info)
    7. {
    8. if (PropertyChanged != null)
    9. {
    10. PropertyChanged(this, new PropertyChangedEventArgs(info));
    11. }
    12. }
    13. }


    weitere Hilfsklasse

    C#-Quellcode

    1. ​public class Cbefehl : ICommand
    2. {
    3. private Action _execute;
    4. public Cbefehl(Action execute)
    5. {
    6. _execute = execute;
    7. }
    8. public bool CanExecute(object parameter)
    9. {
    10. return true;
    11. }
    12. public event EventHandler CanExecuteChanged;
    13. public void Execute(object parameter)
    14. {
    15. _execute();
    16. }
    17. }


    ist das jetzt besser? und "enspricht" das dem MVVM ?
    Hab den Client nach dem Viewmode/View - Prinzip strukturiert und umbenannt.
    Hab die Commands auf LazyLoading umgestellt, nach dem Prinzip:

    C#-Quellcode

    1. private Cbefehl _GetDataCommand;
    2. public ICommand GetDataCommand {
    3. get { return(_GetDataCommand?? (_GetDataCommand=new Cbefehl(OnClick))); }
    4. }
    Auf diese Weise wird nicht bei jedem Abruf ein neuer Cbefehl erstellt, sondern nur genau beim erstmaligen Abruf.

    Habe im Client.MainWindow.Xaml den d:DataContext eingefügt.

    XML-Quellcode

    1. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    2. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    3. mc:Ignorable="d"
    4. d:DesignHeight="300" d:DesignWidth="300"
    5. xmlns:vm="clr-namespace:Client.Viewmodel"
    6. d:DataContext="{d:DesignInstance Type=vm:MainModel}"
    7. >
    Das ermöglicht MVVM: "Binding-Picking" im Xaml-Editor
    Dateien
    @ErfinderDesRades

    ich habe jetzt noch ein paar Fragen...

    1. was bewirken die beiden "??" in dieser Zeile

    C#-Quellcode

    1. ​get { return(_GetDataCommand?? (_GetDataCommand=new Cbefehl(OnClick))); }


    2. warum funktioniert die "laden" Funktion bei mir nicht? wo liegt mein Denkfehler?

    C#-Quellcode

    1. ​public void OnLaden() // funktioniert noch nicht wie gewünscht...
    2. {
    3. Microsoft.Win32.OpenFileDialog dialogo = new Microsoft.Win32.OpenFileDialog();
    4. dialogo.Filter = "Txt-Files(*.txt)|*.txt";
    5. Nullable<bool> result = dialogo.ShowDialog();
    6. if (result == true)
    7. {
    8. ipAddress = File.ReadAllText(dialogo.FileName);
    9. }
    10. Nullable<bool> result2 = dialogo.ShowDialog();
    11. if (result2 == true)
    12. {
    13. portNumber = File.ReadAllText(dialogo.FileName);
    14. }
    15. }


    3. Kann man die Speichern/Laden Funktion "besser" gestalten? oder ist das so wie ich es gemacht habe gut, dass ich zweimal die selbe Funktion in der jeweiligen Methode aufrufe?

    4. wie genau funktioniert das mit den Properties mit dem zweimaligen "anlegen"...einmal mit _ einmal ohne _ ist das wie bei der Deklaration von Variablen denen ich nen Namen zuweise?
    ich meinte die Commands..sry

    C#-Quellcode

    1. private Cbefehl _GetDataCommand;
    2. public ICommand GetDataCommand
    3. {
    4. get { return (_GetDataCommand ?? (_GetDataCommand = new Cbefehl(OnClick))); }
    5. }
    wie kann ich denn vom Viewmodel auf ein Element (Textbox) im View zugreifen?

    C#-Quellcode

    1. ​public void OnLaden() // funktioniert noch nicht wie gewünscht...
    2. {
    3. Microsoft.Win32.OpenFileDialog dialogo = new Microsoft.Win32.OpenFileDialog();
    4. dialogo.Filter = "Txt-Files(*.txt)|*.txt";
    5. Nullable<bool> result = dialogo.ShowDialog();
    6. if (result == true)
    7. {
    8. TextBox der IpAdresse = File.ReadAllText(dialogo.FileName);
    9. }
    10. Nullable<bool> result2 = dialogo.ShowDialog();
    11. if (result2 == true)
    12. {
    13. TextBox der Portnummer = File.ReadAllText(dialogo.FileName);
    14. }
    15. }


    muss ich da in der View ein Binding bei der TextBox machen? Denke schon...aber ich check nicht wie????...

    bisher sieht meine TextBox so aus

    XML-Quellcode

    1. <TextBox Margin="216,72,376,118"
    2. FontWeight="Medium"
    3. FontSize="16"
    4. Name="hostNameFeld"
    5. Text="{Binding ipAddress, UpdateSourceTrigger=PropertyChanged}"
    6. AcceptsReturn="False">
    7. <TextBox.ToolTip>
    8. <ToolTip>
    9. <StackPanel>
    10. <TextBlock FontWeight="Bold">Ip-Adresse/Host Name</TextBlock>
    11. <TextBlock>Tragen Sie hier die Server-Ip-Adresse oder den Server-Hostnamen ein</TextBlock>
    12. </StackPanel>
    13. </ToolTip>
    14. </TextBox.ToolTip>
    15. </TextBox>


    was muss ich da verändern, dass ich beim oben genannten Code das so hinbekomme...
    Du musst zunächst einen DataContext setzen, der auf das ViewModel zeigt und dann kannst Du das Binding nutzen. ​BindingMode und ​UpdateSourceTrigger musst Du dann halt einstellen.

    Grüße
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:

    Runshak schrieb:

    muss ich da in der View ein Binding bei der TextBox machen? Denke schon...aber ich check nicht wie????...
    Ja, was sonst?
    Und ein Binding macht man an Public Properties von Viewmodel-Klassen - wusstest du das noch nicht?
    Dann guck mal meine (unf vmtl. auch annere) Tuts im Wpf-Bereich - da ist immer immer Viewmodel gezeigt mit Public Properties, an die vom Xaml aus gebunden wird.




    Zu deiner OnLaden - Funktion kann ich nix sagen, denn ich weiß ja nicht, wie die funktionieren soll

    Wenn ich genau hingucke, auch den Pseudo-Code, dann willst du mit einem OpenFile-Dialog eine IP-Addresse eingeben?

    Kann das gelingen?? ?(

    Ah - das File wird ausgelesen.

    (ähm - mit einem typisierten Dataset ginge das aber einfacher. Da hättest du eine Datei, und darinnen so viele IP-Addressen wie du magst, und könnte man bequemer auswählen als mit 2 OpenFileDialogen...)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    also das ganze war so gedacht...

    ich hab zwei TextBoxen...

    in die eine TextBox wird die ipAdresse geschrieben und in die andere die Portnummer...

    jetzt gibt es 4 Buttons (davon 3 im Menu)

    1. Button:
    Speichert den Inhalt der beiden TextBoxen in zwei .txt Dateien (wurde so ausgewählt um bei Bedarf etwas daran zu verändern) -> funktioniert

    2. Button:
    soll die beiden gespeicherten .txt Dateien auslesen und in die jeweiligen Textboxen packen...das ging sehr einfach weil ich den Code dafür im Codebehind hatte und nicht schön mit MVVM ...da konnte ich dann einfach

    C#-Quellcode

    1. IpTextBox.Text = ​File.ReadAllText(dialogo.FileName);
    machen... jetzt muss ich das ja übers Binding lösen...und da steh ich grad auf dem Schlauch...

    3. Button:
    schließt das Programm

    4. Button:
    startet das Programm
    Wie gesagt: mit typDataset kannst du im einfachsten Fall ein Grid hinstellen, wo man IP/Port - Datensätze aussuchen, editieren, löschen zufügen kann, ohne dass man iwelche File-Dialoge zu bedienen hätte.

    Aber erstmal stehst du ja auffm Schlauch. Also - hast du post#16 gelesen, Teil eins?
    Was davon hast du nicht verstanden, oder warum ignorierst du das völlig?
    Ja, ich hab den Post gelesen...hab meinen Post nur gemacht, um es nochmal verständlich zu machen, was ich eigentlich möchte...


    also ich hab ein Binding eingerichtet...

    die TextBox hat das hier bekommen...

    XML-Quellcode

    1. ​Text="{Binding ipAddress, UpdateSourceTrigger=PropertyChanged}"


    das hier steht im View-Code

    C#-Quellcode

    1. this.DataContext = new Viewmodel.MainModel();


    das hier im viewmodel

    C#-Quellcode

    1. ​public string ipAddress { get; set; }
    2. public string portNumber { get; set; }


    beim Speichern nehm ich das und schreib es in ne .txt Datei

    C#-Quellcode

    1. ​File.WriteAllText(dialog.FileName, ipAddress);


    und wenn ich das Programm starte nehme ich diesen String und bastel daraus ne Adresse

    C#-Quellcode

    1. ​string rmAddres = null;
    2. rmAddres = "net.tcp://" + ipAddress + ":" + portNumber + "/IvertragAsynchron";


    so das funktioniert alles wunderbar...
    aber beim laden funktioniert es nicht...

    C#-Quellcode

    1. ​ipAddress = File.ReadAllText(dialogo.FileName);


    und warum das nicht funktioniert...bzw wo mein Denkfehler ist...das versteh ich nicht...ja ich hab mir dein Tut über das Binding-Picking angeschaut...und ich hab mein Programm so umgebaut, wie du mir gestern geraten hast...aber ich versteh im Augenblick wirklich nicht was ich falsch gemacht habe...bzw was ich vergessen habe zu tun...