Laden...

XML Binding aktualisieren ListBox

Erstellt von NameInvalid vor einem Jahr Letzter Beitrag vor einem Jahr 538 Views
N
NameInvalid Themenstarter:in
4 Beiträge seit 2021
vor einem Jahr
XML Binding aktualisieren ListBox

Guten Abend,

ich bin aktuell dabei eine kleine simple und universelle Datenbank auf Basis einer XML Datei zu programmieren, in diesem Fall als Beispiel ein simples Kochbuch. Das Binding und die Darstellung der Daten habe ich soweit hinbekommen und auch das Speichern geänderter Daten funktioniert soweit. Als nächstes arbeite ich an einer Funktion um einen neues Element in der Datenbank bzw. der XML zu erzeugen, dies funktioniert auch soweit. Ich stehe nun vor dem Problem, dass meine Listbox mit der Auflistung dieser Elemente Probleme macht, da die neu erzeugten Elemente nicht angezeigt werden, da der XML Provider diese nicht neu lädt. Nach einigen Stunden suche bin ich nun soweit, dass ich mich wohl mit dem "INotifyPropertyChanged" anfreunden muss, ich habe die Klassen bzw. das Model dafür erstellt, nur funktioniert das ganze nicht da ich wohl nach dem falschen Element Ausschau halte und versuche es nun hier mal im Forum.

XAML:


<Window x:Class="EinerDerTests.MainWindow"
        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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EinerDerTests"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Window.DataContext>
        <local:KochbuchModel/>
    </Window.DataContext>
    
    <Window.Resources>

        <DataTemplate x:Key="KochbuchTemplate">
            <Label Content="{Binding XPath=Name}"/>
        </DataTemplate>

    </Window.Resources>

    <Grid Margin="0,10,0,0">

        <Grid.DataContext>
            <XmlDataProvider x:Name="Kochbuch" Source="KochbuchTest.xml" XPath="Kochbuch/Rezept" />
        </Grid.DataContext>

        <Grid.ColumnDefinitions>
            <ColumnDefinition MinWidth="150" MaxWidth="300"/>
            <ColumnDefinition MinWidth="300" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
        </Grid.RowDefinitions>

        <DockPanel Grid.Column="0" Margin="5,0,0,0">
            <Border Height="30" Padding="0" Background="#4E87D4" DockPanel.Dock="Top">
                <Label VerticalAlignment="Center" Foreground="White">Rezepte</Label>
            </Border>

            <ListBox x:Name="RezeptListBox" Margin="0,0,0,20" DockPanel.Dock="Left"
                     ItemsSource="{Binding}"
                     ItemTemplate="{StaticResource KochbuchTemplate}"
                     IsSynchronizedWithCurrentItem="True"
                     Visibility="Visible" SelectionMode="Single">
            </ListBox>
        </DockPanel>

        <StackPanel Grid.Column="1" Margin="0,0,5,0">

            <StackPanel Orientation="Horizontal">
                <Label VerticalAlignment="Top" HorizontalAlignment="Right" FontWeight="Bold" MinWidth="80">Name:</Label>
                <TextBox Width="300" Margin="0,0,0,0" Text="{Binding XPath=Name}" VerticalAlignment="Center" BorderBrush="{x:Null}" />
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <Label VerticalAlignment="Top" HorizontalAlignment="Right" FontWeight="Bold" MinWidth="80">Aufwand:</Label>
                <TextBox Width="300" Margin="0,0,0,0" Text="{Binding XPath=Aufwand}" VerticalAlignment="Center" BorderBrush="{x:Null}" />
            </StackPanel>

        </StackPanel>

        <DockPanel Grid.Column="1">
            <Button x:Name="RezeptSpeichernButton" Click="RezeptSpeichernButton_Click" Height="20" Width="150">Rezept Aktualisieren</Button>
            <Button x:Name="RezeptErstellenButton" Click="RezeptErstellenButton_Click" Height="20" Width="150">Rezept Erstellen</Button>
        </DockPanel>

    </Grid>
 
</Window>

Code behind:


using System;
using System.Collections.Generic;
using System.Linq;
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;
using System.Xml;

namespace EinerDerTests
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

 

        public MainWindow()
        {
            InitializeComponent();
            Kochbuch.Source = new Uri("C:/Users/admin/source/repos/EinerDerTests/KochbuchTest.xml");
        }

        private void RezeptSpeichernButton_Click(object sender, RoutedEventArgs e)
        {
            string source = Kochbuch.Source.LocalPath;
            Kochbuch.Document.Save(source);
        }
        private void RezeptErstellenButton_Click(object sender, RoutedEventArgs e)
        {

            XmlDocument Kochbuch = new XmlDocument();
            string source = "C:/Users/admin/source/repos/EinerDerTests/KochbuchTest.xml";
            Kochbuch.Load(source);
            ....
            Kochbuch.Save(source);

        }

    }
}

KochbuchModel.cs:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EinerDerTests
{
    class KochbuchModel
    {
        private string _KochbuchTemplate;

        public string KochbuchTemplate
        {
            get { return _KochbuchTemplate; }
            set { _KochbuchTemplate = value; }
        }

    }
}

ObservableObject.cs


using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace EinerDerTests
{
    class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyname = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
        }
    }
}

Der Code ist noch ziemlich experimentell und an der ein oder anderen Stelle noch murks, aber das ganze dient ja hauptsächlich dass das mal funktioniert

Gruß

16.833 Beiträge seit 2008
vor einem Jahr

Das Binding und die Darstellung der Daten habe ich soweit hinbekommen und auch das Speichern geänderter Daten funktioniert soweit.

Mh. Ne 🙂
Was Du da gemacht hast, ist nicht, was man unter Datenbindung versteht.
In WPF macht man das mit Hilfe von MVVM und entsprechenden ViewModels.
[Artikel] MVVM und DataBinding

Bei MVVM brauchst das ganze Thema Code Behinds und Click-Events nicht.
Da macht man das mit Commands, und eben diesen View Model (für die View).
Das ViewModel kennt dann wiederum zB. Logik-Modelle.

--
Nur als Info, rein technisch, weil Du von "Datenbank" sprichst:
Mit Dein XML-Load, in dieser Form, lädst führst Du Datenbank-Operationen direkt in der UI aus
-> [Artikel] Drei-Schichten-Architektur

Aber fix erstmal das MVVM Thema.

D
6 Beiträge seit 2022
vor einem Jahr

Moin,

Du verwendest hier nicht wirklich MVVM (Model View View Model). Dabei geht es darum das du relativ wenig in deine Klasse schreibst und die eigentliche Logik in anderen Klassen machst. Erstelle hierfür eine Klasse wie auch immer du diese nennen möchstest. In die Klasse wo du aktuell deine Events drinnen hast kannst du ein DataContext erstellen mit dem Verweis auf deinen ViewModel.

sprich:


DataContext = new ViewModel();

Nun kannst mit der Klasse ViewModel.cs Arbeiten.

Du gibst in der XAML Datei z.B. einen Button ein Binding:


<Button Command="{Binding Path=Cmd1}" x:Name="btn1" Content="1" HorizontalAlignment="Left" Margin="172,127,0,0" VerticalAlignment="Top" FontSize="16" Width="30" Height="30"/>

Es ist wichtig das ein Pfad eingegeben ist da du mit diesem dann Arbeitest.

Im ViewModel.cs wird die INotifyPropertyChanges vererbt.
Dannach kannst du ICommands erstellen bei denen du das die MEthode einfügst z.B:


private ICommand _mediumCommand;
public ICommand MediumCommand
        {
            get
            {
                if (_mediumCommand == null)
                    _mediumCommand = new RelayCommand(param => SelectMedium(), param => CanExecuteSelectMedium());
                return _mediumCommand;
            }
        }

Die Klasse RelayCommand.cs musst du dir selbst im Projekt erstellen, hierfür Google einfach.

Bei Fragen schreibe einfach!

LG