2010-07-17 5 views
0

J'ai un DataGrid dans un WPF peuplé d'un fichier csv. Ceci est fait avec Linq et remplit la grille de données via CollectionViewSource.Source.Mise à jour de WPF DataGrid

L'exigence est pour toutes les mises à jour/modifications apportées aux données dans le DataGrid pour ensuite être réenregistrés dans le csv.

J'ai besoin de savoir comment enregistrer les modifications apportées aux données? J'ai joué avec certains des événements et datacontext et similaires, mais rien ne fonctionne encore.

Excusez-moi si c'est la question du type d'un débutant. Le passage des applications Windows à WPF est une courbe d'apprentissage abrupte (pour moi au moins). Je viens de peupler un tableau pour l'instant pendant que j'essaie de comprendre. Fondamentalement, je veux juste récupérer les données à nouveau, enregistrez-le comme var.

System.Windows.Data.CollectionViewSource personViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("personViewSource"))); 

     List<Person> T = new List<Person>(); 
      Person p = new Person(); 

      string[] str = new string[] { "Stacey", "Olivia", "Dylan", "Lauryn", "Beth", "Caitlin" }; 
      var data = from s in str 
        select s; 
      Person pers; 
      foreach (var d in data) 
      { 
       pers = new Person(); 
       pers.Name = d; 
       pers.Age = 22; 
       T.Add(pers); 
      } 


     personViewSource.Source = T; 

Le XAML:

<Window x:Class="WpfApplication4.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Name="win1" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:my="clr-namespace:WpfApplication4"> 
<Window.Resources> 
    <CollectionViewSource x:Key="personViewSource" d:DesignSource="{d:DesignInstance my:Person, CreateList=True}" /> 
</Window.Resources> 
<StackPanel Width="369" Height="230" DataContext="{StaticResource personViewSource}"> 
    <DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Name="personDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Width="88" HorizontalAlignment="Left" BorderThickness="4" Background="#FFF8C5C5" SelectionChanged="personDataGrid_SelectionChanged" TextInput="personDataGrid_TextInput" RowEditEnding="personDataGrid_RowEditEnding" TargetUpdated="personDataGrid_TargetUpdated"> 
     <DataGrid.Columns> 
      <DataGridTextColumn x:Name="nameColumn" Binding="{Binding Path=Name, Mode=TwoWay, NotifyOnTargetUpdated=True}" Header="Name" Width="SizeToHeader" /> 
      <DataGridTextColumn x:Name="ageColumn" Binding="{Binding Path=Age}" Header="Age" Width="SizeToHeader" Foreground="#FFC14040" /> 
     </DataGrid.Columns> 
    </DataGrid> 
</StackPanel> 

Merci

+0

Comment voulez-vous que cela fonctionne? Le DataGrid doit-il enregistrer les valeurs dans un fichier automatiquement? Ou chaque fois qu'un bouton est poussé ou quelque chose d'aussi manuel? En outre, peut-être nous montrer le code pour obtenir les données dans le DataGrid en premier lieu serait utile. – Goblin

+0

Soit automatiquement ou via un bouton de soumission. Je me bats juste pour obtenir ma tête autour de lui – Chris

+0

vos données s'affichent correctement? parce que s'il est en train d'éditer, il devrait mettre à jour votre objet person, mettre un point d'arrêt sur l'un des setters d'une propriété pour être sûr. –

Répondre

1

Vous pouvez écouter l'événement lorsque la cellule se termine la modification et puis enregistrez votre source de données. à savoir la prise dans votre constructeur du contrôle qui héberge la grille (probablement un contrôle utilisateur, la fenêtre, la page, etc.) après l'appel InitializeComponent()

this.myDataGrid.CellEditEnding += new EventHandler<DataGridCellEditEndingEventArgs>(grid_CellEditEnding); 

et ont le gestionnaire de sauvegarde de la source de données

void grid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { 
    //save my data source 
    } 

personnellement, je préfère l'approche où vous pouvez effectuer vos modifications, puis cliquez sur enregistrer à la fin, mais dans votre cas, vous pouvez utiliser String.Join pour créer une chaîne et puis CSV écrire dans un fichier.

Pour ce faire, faites une propriété qui est votre liste, de sorte que votre bâtiment de vos données pour la grille ressemblerait à ceci:

public Collection<Person> MyPersonDataSource {get; private set; } 

public MyWindowsConstructor() { 
    //build the grid data before you initialize the window, as the PersonDataSource 
    //does not implement NotifyPropertyChanged, if you build the data afterwards 
    //the binding won't be updated 
    BuildGridData(); 
    InitializeComponent(); 
} 


private void BuildGridData(){ 

    this.MyPersonDataSource = new Collection<Person>(); 
    Person p = new Person(); 

    string[] str = new string[] { "Stacey", "Olivia", "Dylan", "Lauryn", "Beth", "Caitlin" }; 
    var data = from s in str 
      select s; 
    Person pers; 
    foreach (var d in data) 
    { 
    pers = new Person(); 
    pers.Name = d; 
    pers.Age = 22; 
    this.MyPersonDataSource.Add(pers); 
    } 
} 

puis dans votre édition fin cellulaire fonction

void grid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e) { 
    //save my data source 
    var nameArray = this.MyPersonDataSource.Select(item => item.Name).ToArray(); 
    //create the csv string 
    String csvString = String.Join("," nameArray); 
    //write it to a file 
    System.IO.File.WriteAllText(@"C:\SomeFolderYouHavePermissionsOn\names.csv", csvString); 
    } 

je lie ma grille directement à la MyPersonDataSource de la propriété, comme si ..

<Window x:Class="WpfApplication4.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Name="win1" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:my="clr-namespace:WpfApplication4"> 
<Window.Resources> 
    <CollectionViewSource x:Key="personViewSource" Source="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=MyPersonDataSource}" d:DesignSource="{d:DesignInstance my:Person, CreateList=True}" /> 
</Window.Resources> 
<StackPanel Width="369" Height="230" DataContext="{StaticResource personViewSource}"> 
    <DataGrid AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding}" Name="personDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Width="88" HorizontalAlignment="Left" BorderThickness="4" Background="#FFF8C5C5" SelectionChanged="personDataGrid_SelectionChanged" TextInput="personDataGrid_TextInput" RowEditEnding="personDataGrid_RowEditEnding" TargetUpdated="personDataGrid_TargetUpdated"> 
     <DataGrid.Columns> 
      <DataGridTextColumn x:Name="nameColumn" Binding="{Binding Path=Name, Mode=TwoWay, NotifyOnTargetUpdated=True}" Header="Name" Width="SizeToHeader" /> 
      <DataGridTextColumn x:Name="ageColumn" Binding="{Binding Path=Age}" Header="Age" Width="SizeToHeader" Foreground="#FFC14040" /> 
     </DataGrid.Columns> 
    </DataGrid> 
</StackPanel> 
</Window> 

Et je envisagerait probablement un stockage de données plus robuste que le CSV, vous pouvez utiliser xml et vous lier à l'aide de XPath, mais je n'en ai pas assez utilisé pour encadrer une réponse appropriée.

+0

Comment enregistrer la source de données? – Chris

+0

Aran merci. Pourriez-vous expliquer comment le lier directement à myPersonDataSource? Si je convertis tous les csv en xml, y at-il un meilleur moyen? – Chris

+0

Si je ne me trompe pas DataGrid.CellEditEnding événement se déclenche pour chaque cellule qui est modifiée, non? Supposons que l'utilisateur parcourt la grille et modifie les valeurs dans Cell1, Cell2 et Cell3 de RowA. Ai-je raison de m'attendre à ce que DataGrid.CellEditEnding se déclenche 3 fois? Si c'est le cas, cela me semble un peu excessif - enregistrer les changements de grille sur chaque édition. Mais quoi de plus important, comment puis-je implémenter la validation des lignes? Parce que dans de nombreux scénarios, une valeur dans Cell1 peut générer des choix disponibles pour Cell2 et ainsi de suite => vous pouvez uniquement valider et enregistrer la ligne entière, pas cellule par cellule. – Astrogator

Questions connexes