Laden...

Alle Einträge aus einer ListView inkl. Spalte und Zeile auslesen

Erstellt von TigerCrow vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.981 Views
T
TigerCrow Themenstarter:in
86 Beiträge seit 2017
vor 5 Jahren
Alle Einträge aus einer ListView inkl. Spalte und Zeile auslesen

Hallo zusammen,

Habe ein Problem mit WPF und Listview, habe hier leider nix passendes gefunden 🙁

Ich möchte **alle Einträge **aus der ListView auslesen, also Zeile und die dazugehörige Spalte.

Habe jetzt im XAML vollgendes:


<ListView x:Name="DZeiten" Margin="535,0,0,43" HorizontalAlignment="Stretch">
            <ListView.ContextMenu>
                <ContextMenu>
                    <MenuItem Header="Löschen"/>
                </ContextMenu>
            </ListView.ContextMenu>
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Thema   " Width="Auto" DisplayMemberBinding="{Binding Path=Thema}"/>
                    <GridViewColumn Header="Anfangszeit   " Width="Auto" DisplayMemberBinding="{Binding Path=Anfangszeit}"/>
                    <GridViewColumn Header="Endzeit   " Width="Auto" DisplayMemberBinding="{Binding Path=Endzeit}"/>
                </GridView>
            </ListView.View>
        </ListView>

Zeilen einfüge mache ich mit:



DZeiten.Items.Add(
                    new
                    {
                        Thema = ThemenAuswahl.SelectedValue.ToString(),
                        Anfangszeit = ADatum.SelectedDate.Value.ToString("dd.MM.yyyy"),
                        Endzeit = EDatum.SelectedDate.Value.ToString("dd.MM.yyyy"),
                    });


Nur wie bekomme ich das wieder ausgelesen?



for (int t = 0; t < DZeiten.Items.Count; t++)
                {
                    MessageBox.Show(DZeiten.Items[t].ToString());
                }


Hier kommt die gesammte Kette 🙁 also { Thema = HTML, Anfangszeit = 20.05.2018, Endzeit = 22.05.2018 }

Kann das auch net ansprechen mit: DZeiten.Items[t].Thema
Kommt Fehler

Wie bekomme ich jetzt die einzelnen Spalten?
Steh da auf dem schlauch!

Wäre nett wenn mir jemand helfen könnte 🙂

Lieben Gruß
TigerCrow

4.942 Beiträge seit 2008
vor 5 Jahren

Durch die Verwendung eines Anonymous Types kannst du nicht wieder auf diesen Typen außerhalb zugreifen. Erstelle dafür eine eigene Klasse und 'caste' dann beim Zugriff darauf.

Viel besser wäre jedoch, wenn du DataBinding, d.h. MVVM benutzt und in einem ViewModel die Daten hältst (dann benötigst du auch keine Typumwandlung mehr).

T
TigerCrow Themenstarter:in
86 Beiträge seit 2017
vor 5 Jahren

Danke

Das habe ich mir schon fast gedacht ...

Win Forms sind da sowas von einfacher ... aber na ja

Aber .. hat jemand zufällig ein kleines Beispiel wie ich ein Mehrspaltiges Listview befülle und auch wieder auslesen kann?

z.B.

2 Spalten: Vorname, Nachname

Wie setzte ich die Werte und wie lese ich diese wieder aus ohne was selectiert zu haben und wenn möglich ohne Klasse zu erstellen!

Gruß
TigerCrow

2.080 Beiträge seit 2012
vor 5 Jahren

Mag sein, dass WinForms vom Konzept direkter ist. Du wirst ein Control hin und arbeitest damit, ist doch wunderbar einfach.
Allerdings wird das früher oder später zu einer Schwäche, bei größeren Projekten verlierst Du zwangsläufig den Überblick.
WPF ist der Versuch, View und Logik (der View) von einander zu trennen, damit Du eben nicht so leicht den Überblick verlierst. Gleichzeitig macht es ein Projekt flexibler, es macht deine Anwendung leichter testbar, etc.
Außerdem bietet WPF noch so einige andere Vorteile, wie z.B. ein gut funktionierendes DataBinding.

wenn möglich ohne Klasse zu erstellen!

Warum nicht? Ohne geht es zwar, allerdings verschenkst Du damit alle Vorteile.

Ein kleines Beispiel:

// Jedes ViewModel sollte INotifyPropertyChanged implementieren, damit WPF auf Änderungen im ViewModel reagieren kann.
// Diese Implementierung liegt in der ViewModelBase-Klasse (s.u.)
public class UserViewModel : ViewModelBase
{
	private string _name;
	private int _age;
	private string _mail;
	
    public string Name
	{
		get { return _name; }
		set
		{
			_name = value;
			// Damit WPF bemerkt, dass der Wert sich geändert hat, muss das entsprechende Event ausgeführt werden.
			RaisePropertyChanged(nameof(Name));
		}
	}
    public int Age
	{
		get { return _age; }
		set
		{
			_age = value;
			RaisePropertyChanged(nameof(Age));
		}
	}
    public string Mail
	{
		get { return _mail; }
		set
		{
			_mail = value;
			RaisePropertyChanged(nameof(Mail));
		}
	}
}

// Ich persönlich baue für jedes UserControl ein ViewModel - nicht immer, aber meistens.
// Das hier soll also das ViewModel für die ListView sein.
// Ob sich hier ein eigenes ViewModel lohnt, sei mal dahin gestellt, als Beispiel schadet es aber sicher nicht.
public class UserListViewModel : ViewModelBase
{	
	// Die ObservableCollection implementiert INotifyCollectionChanged. WPF reagiert darauf und kann die Änderungen in der Liste live aktualisieren
	public ObservableCollection<UserViewModel> Users { get; }
	
	public UserListViewModel()
	{
		Users = new ObservableCollection<UserViewModel>();
	}
	
	// Die ist nur zu Demonstrationszwecken da
	public void AddUser(int i)
	{
		var user = new UserViewModel()
		{
			Name = "Name" + i,
			Age = 20 + i,
			Mail = "Mail" + i,
		};
		
		Users.Add(user);
	}
}

// Das ist eine allgemeine Basis-Klasse, die Du für jedes ViewModel brauchst.
// Die wichtigste Aufgabe ist, das INotifyPropertyChanged-Interface zu implementieren, denn nur durch dieses Interfaces bekommt WPF mit, ob sich eine Property ändert und kann das dann automatisch aktualisieren.
// Für diese Klasse gibt es viele Konzepte. Ich mag die Variante ganz gerne, wo eine Property nur noch aus GetValue() und SetValue() besteht. Wegen der Einfachheit belasse ich es aber bei dieser rudimentären Variante.
public class ViewModelBase : INotifyPropertyChanged
{
	public event PropertyChangedEventHandler PropertyChanged;
	
	protected void RaisePropertyChanged(string propertyName)
	{
                // Führt das Event aus und gibt den Property-Namen als Argument mit, damit WPF reagieren kann.
		PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
	}
}
<Window xmlns:viewModel="clr-namespace:MySample.ViewModel;assembly=MySample">
	<Window.DataContext>
		<!-- Das sorgt dafür, dass WPF weiß, auf welche ViewModel-Instanz es die Bindings beziehen muss.
		Den DataContext kann man auch im CodeBehind oder mit einem Binding setzen. 		-->
		<viewModel:UserListViewModel />
	</Window.DataContext>
	
	<!-- Ein Binding besagt, dass die View-Property (ItemsSource) an die ViewModel-Property gebunden wird.
	Ändert sich die ViewModel-Property (Das Event INotifyPropertyChanged.PropertyChanged wird ausgeführt), dann erhält auch die View-Property den neuen Wert automatisch zugewiesen
	In diesem Fall handelt es sich um eine View-Property, die Collections verarbeiten kann und die auf Änderungen derselben reagiert.
	Dafür braucht man das INotifyCollectionChanged-Interface, was von der ObservableCollection implementiert wird. -->
	<ListView ItemsSource="{Binding People}">
		<ListView.View>
			<GridView>
				<!-- In diesem Fall wird jedes Binding auf jedes einzelne Item der Quelle bezogen, also auf ein einzelnes UserViewModel. Oder anders ausgedrückt: Der DataContext ist bei diesen Bindings ein UserViewModel.
				Die Columns "wissen" also anhand des Bindings, wie sie die Quelle eines Wertes finden können und weisen die jeder einzelnen Zelle automatisch zu.
				Ändert sich z.B. der Name, wird auch der Wert in der View automatisch aktualisiert. -->
				<GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
				<GridViewColumn Header="Alter" Width="50" DisplayMemberBinding="{Binding Age}" />
				<GridViewColumn Header="Mail" Width="150" DisplayMemberBinding="{Binding Mail}" />
			</GridView>
		</ListView.View>
	</ListView>
</Window>

Das Beispiel ist sicher nicht vollständig (z.B. fehlen am Window noch min. ein Namespace) und getestet habe ich es auch nicht. Ich denke aber, dass das dem eigentlichen Sinn, ein Beispiel zu sein, keinen Abbruch tut.

Ach ja, schau mal hier rein:
http://openbook.rheinwerk-verlag.de/visual_csharp_2012/
Das dürfte so einige Fragen klären, da wird auch WPF ausführlich thematisiert.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

5.658 Beiträge seit 2006
vor 5 Jahren

Hi TigerCrow,

Win Forms sind da sowas von einfacher ... aber na ja

Wenn du WPF nicht so verwendest, wie es gedacht ist, dann solltest du dich auch nicht darüber beschweren, daß es alles sehr umständlich ist.

Du hast unter WPF die Möglichkeit, DataBinding zu verwenden. Das nimmt dir eine Menge Arbeit ab, und du brauchst Daten nicht aus Steuerelementen auszulesen, zu casten usw., sondern du kannst einfach die Daten in der richtigen Struktur bearbeiten. Warum sollte man das nicht verwenden?

hat jemand zufällig ein kleines Beispiel wie ich ein Mehrspaltiges Listview befülle und auch wieder auslesen kann?

Beispiele dafür gibt es im Netz oder in [Artikel] MVVM und DataBinding

Weeks of programming can save you hours of planning

T
TigerCrow Themenstarter:in
86 Beiträge seit 2017
vor 5 Jahren

Danke Palladin007 für diene SUPER Erklärung! Du könntest als Dozent durchgehen 🙂

Versuche das mal das nächste mal wie beschrieben zu machen!

Gruß
TigerCrow