【问题标题】:WPF Update from datagrid从数据网格更新 WPF
【发布时间】:2010-07-17 13:25:34
【问题描述】:

我在从 csv 文件填充的 WPF 中有一个数据网格。 这是通过 Linq 完成的,并通过 CollectionViewSource.Source 填充数据网格。

要求对数据网格中的数据进行的任何更新/更改都保存回 csv。

我需要知道如何保存对数据的任何更改?我一直在玩一些事件和数据上下文等,但还没有任何效果。

如果这是初学者的问题,我深表歉意。从 Windows 应用程序迁移到 WPF 是一个陡峭的学习曲线(至少对我而言)。 我现在只是从一个数组中填充,同时我试图弄清楚。基本上就是想把数据再拿出来,另存为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;

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>

谢谢

【问题讨论】:

  • 您希望它如何工作?数据网格是否应该自动将值保存到文件中?或者每当按下按钮或同样手动的东西时?此外,也许首先向我们展示将数据导入 DataGrid 的代码会有所帮助。
  • 自动或通过提交按钮。我只是在努力解决它
  • 您的数据显示正确吗?因为如果它正在编辑它应该更新您的人员对象,请在属性的设置器之一上放置一个断点以确保。
  • 用上面的代码保证数据正确显示。
  • 不用担心,克里斯,对我的回答进行了编辑

标签: c# wpf datagrid


【解决方案1】:

您可以在单元格结束编辑时监听事件,然后保存您的数据源。即在 InitializeComponent() 调用之后将其放置在承载网格的控件(可能是用户控件、窗口、页面等)的构造函数中

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

然后让处理程序保存数据源

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

我个人更喜欢执行编辑然后在最后点击保存的方法,但在您的情况下,您可以使用 String.Join 创建一个 CSV 字符串,然后将其写入文件。

为此,请创建一个属性,即您的列表,这样您为网格构建的数据将如下所示:

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);
  }
}

然后在你的单元格结束编辑功能

  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);
  }

我会将我的网格直接绑定到属性 MyPersonDataSource,就像这样......

<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>

而且我可能会考虑比 CSV 更强大的数据存储,您可以使用 xml 并使用 XPath 绑定到它,但我还没有充分利用它来构建适当的答案。

【讨论】:

  • 如何保存数据源?
  • 阿兰谢谢。你能解释一下如何将它直接绑定到 myPersonDataSource 吗?如果我将所有 csv 转换为 xml,还有更好的方法吗?
  • 如果我没记错的话,DataGrid.CellEditEnding 事件会为每个被修改的单元格触发,对吧?假设用户通过网格并修改 RowA 的 Cell1、Cell2 和 Cell3 中的值。我期望 DataGrid.CellEditEnding 触发 3 次是否正确?如果是这样,对我来说似乎有点过分 - 在每次编辑时保存网格更改。但更重要的是,我如何实现行验证?因为在许多情况下,Cell1 中的值可能会驱动 Cell2 等可用的选择 => 您只能验证和保存整行,而不是逐个单元格。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-06
  • 1970-01-01
  • 2013-06-10
  • 1970-01-01
相关资源
最近更新 更多