Laden...

ListView mit Formular -> SelectionChanged prüfen ob Änderungen

Erstellt von resper vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.391 Views
R
resper Themenstarter:in
33 Beiträge seit 2017
vor 7 Jahren
ListView mit Formular -> SelectionChanged prüfen ob Änderungen

Hallo,

Also ich habe ein ListView Element mit einem Formular verknüpft.
Ich möchte nun, dass wenn der Nutzer einen anderen Eintrag auswählt geprüft wird ob im Formular was geändert wurde und wenn ja, gefragt wird ob die Änderung gespeichert werden soll.

In meiner XAML sieht das momentan so aus:

<ListView Name="UserList" ItemsSource="{Binding Mode=OneWay}" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" SelectionMode="Single">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="ID" DisplayMemberBinding="{Binding Id}" />
            <GridViewColumn Header="Nachname" DisplayMemberBinding="{Binding Lastname}" />
            <GridViewColumn Header="Vorname" DisplayMemberBinding="{Binding Firstname}" />
            <GridViewColumn Header="Personal ID" DisplayMemberBinding="{Binding PersId}" />
            <GridViewColumn Header="Login" DisplayMemberBinding="{Binding Login}" />
        </GridView>
    </ListView.View>
</ListView>
<Border Style="{StaticResource CardMarginTop}" Grid.Column="0" Grid.Row="1">
    <StackPanel Orientation="Vertical">
        <Label Content="Nutzer Details" Style="{StaticResource CardTitle}" />
        <Grid Style="{StaticResource FormGrid}" DataContext="{Binding SelectedItem, ElementName=UserList}">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Label Content="Vorname:" Grid.Row="0" Grid.Column="0" />
            <Label Content="Nachname:" Grid.Row="1" Grid.Column="0" />
            <Label Content="Personal ID:" Grid.Row="2" Grid.Column="0" />
            <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Firstname}"/>
            <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Lastname}"/>
            <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding PersId}"/>
        </Grid>                    
    </StackPanel>
</Border>

Code behind:

    public partial class ManageAccounts : Page
    {
        public ManageAccounts()
        {
            InitializeComponent();
            List<UserModel> userList = MainWindow.sqlHelper.GetAllUser();
            UserList.DataContext = userList;
        }
    }
M
9 Beiträge seit 2011
vor 7 Jahren

Hoi resper,

Es stellt sich die Frage, was ist MainWindow.sqlHelper.GetAllUser() ?

Ist GetAllUsers() eine Tabelle. eine ObservableCollection<T> oder eine List<T> ?

Ich würde GetAllUsers als ObservableCollection<T> implemtieren, und im MainWindow den CollectionChanged.Event abfangen. Den Event kannst du so abfangen:


private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            bool itemChanged = false;
            if(!e.OldItems.Equals(e.NewItems))
            {
                for(int i =0; i<e.OldItems.Count;i++)
                {
                    if(!e.NewItems[i].Equals (e.OldItems[i]) )
                    {
                        itemChanged = true;
                    }
                }
            }

            if (itemChanged)
            {
                // Mache etwas!!
            }
        }

Gruss Alex

P
441 Beiträge seit 2014
vor 7 Jahren

Das selektierte Element ist kein Teil der Collection/Liste, sondern ein Teil der Oberfläche. Insofern wirst du auch bei einer ObservableCollection<T> nicht mitbekommen, wenn sich das selektierte Element ändert, diese reagiert nur auf Änderungen der Collection.

Es gibt denke ich zwei Elegante Lösungen hierfür:*SelectedItem der Oberfläche an eine Property aus dem ViewModel binden *Per Interactivity ein ICommand auslösen, wenn sich das selektierte Element ändert.

Edit: Tippfehler

R
resper Themenstarter:in
33 Beiträge seit 2017
vor 7 Jahren

Ok, also ich habe es jetzt ein bsichen geändert.

XAML:

<StackPanel Orientation="Vertical">
    <Label Content="Nutzer Details" Style="{StaticResource CardTitle}" />
    <Grid Style="{StaticResource FormGrid}" DataContext="{Binding SelectedItem, ElementName=UserList}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Label Content="Vorname:" Grid.Row="0" Grid.Column="0" />
        <Label Content="Nachname:" Grid.Row="1" Grid.Column="0" />
        <Label Content="Personal ID:" Grid.Row="2" Grid.Column="0" />
        <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Firstname}" />
        <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Lastname}" />
        <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding PersId}" />
    </Grid>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
        <Button x:Name="CancleEdit" Content="Abbrechen" Margin="10,0"/>
        <Button x:Name="SaveEdit" Content="Speichern" />
    </StackPanel>
</StackPanel>

Code Behind:

AdminModel admin = new AdminModel()
{
    UserList = MainWindow.sqlHelper.GetAllUser()
};
UserList.DataContext = admin.UserList;

Im Admin Model sieht das jetzt so aus:

namespace resper.LaMa.Models
{
    public class AdminModel : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;
        private List<UserModel> _UserList;
        public List<UserModel> UserList
        {
            get { return _UserList; }
            set
            {
                _UserList = value;
                OnPropertyChanged("UserList");
            }
        }
        private void OnPropertyChanged(string name)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
        }
    }
}

In der SqlHelper sieht das ganze so aus:

public List<UserModel> GetAllUser()
{
    List<UserModel> allUser = new List<UserModel>();

    SQLiteDataReader sdr = Query("SELECT * FROM user");
    while (sdr.Read())
    {
        allUser.Add(new UserModel(sdr));
    }

    return allUser;
}

Ziel ist es jetzt, dass wenn der Anwender einen anderen Eintrag auswählt, zu prüfen ob der vorherige Eintrag geändert wurde und per Popup zu fragen ob die Änderung gespeichert werden soll wenn er nicht vorher den Speicher Button gedrückt hat

P
441 Beiträge seit 2014
vor 7 Jahren

Nein - das solltest du dir auch selber beantworten können - schließlich hast du nichts dergleichen implementiert.

Das was du hier implementiert hast, liest die Daten aus der Datenbank und die GUI stellt fest, wenn du dies tust (INotifyPropertyChanged).

Was nicht festgestellt wird ist:
* Wenn etwas an einem User geändert wird
* Wenn der selektierte Benutzer gewechselt wird

Wie du das wechseln erkennen kannst hatte ich oben geschrieben. Wenn du erkennen möchtest, ob an einem Benutzer etwas geändert wurde, brauchst du soetwas wie ein "IsDirty" Flag:


class UserViewModel
{
	private string _name;
	
	public string Name
	{
		get { return _name; }
		set
		{
			_name = value;
			IsDirty = true;
		}
	}

	public bool IsDirty { get; set; } = false;
}

Damit kannst du dann beim Wechsel herausfinden, ob etwas an dem Benutzer geändert wurde.

5.658 Beiträge seit 2006
vor 7 Jahren

Hi resper,

ich empfehle die Artikel [Artikel] Drei-Schichten-Architektur und [Artikel] MVVM und DataBinding. Im zweiten Artikel gibt es auch ein Beispiel für eine ListView, die genau deine Anforderungen entspricht:


<ListView ItemsSource="{Binding Employees}" DisplayMemberPath="FullName" SelectedItem="{Binding SelectedEmployee}" />

Weeks of programming can save you hours of planning

R
resper Themenstarter:in
33 Beiträge seit 2017
vor 7 Jahren

Ja mit dem MVVM Artikel habe ich mich auch schon versucht auseinanderzusetzen, habe auch schon versucht mich mit Hilfe eines Buches (https://www.rheinwerk-verlag.de/c-6-mit-visual-studio-2015_3819/) schlau zu machen aber irgendwie fehlen mir da wohl noch ein paar Grundlagen.

R
resper Themenstarter:in
33 Beiträge seit 2017
vor 7 Jahren

Das mit dem Edit hatte ich mir auch schon überlegt, werde es mal probieren mit den beiden Vorschlägen. Danke für die Tipps