【问题标题】:Select multiple cells in DataGrid and output to Excel sheet在 DataGrid 中选择多个单元格并输出到 Excel 表
【发布时间】:2011-04-05 09:51:12
【问题描述】:

我有一个包含数百行和两列数据的 DataGrid。我需要以编程方式选择 DataGrid 中的某些行和某些特定单元格,并将它们输出到 Excel 工作表上。 经过一番研究,似乎获得单元格值的唯一方法是编写一个辅助函数,每次获得一个单元格值时都会运行辅助函数。

是否有更简单/更快的方法来获取 DataGrid 中特定单元格的值?或者我应该在每个单元格值转到 DataGrid 并将数组输出到 Excel 而不是 DataGrid 时同时将其存储到数组中?

【问题讨论】:

    标签: c# wpf datagrid datagridcell


    【解决方案1】:

    假设DataGrid显示员工信息,对于每个员工,我们存储他的IdNameAddress。让我们为每个员工属性(例如IdIsIdSelectedNameIsNameSelected)添加一个额外的布尔属性,这个布尔属性将绑定到DataGrid.IsSelected 属性,因此,它表示单元格是否被选中与否,您也可以通过将其设置为True,以编程方式使用它来选择显示指定属性的单元格。见以下代码:

    /// <summary>
    /// A class that represents an employee. Notice that with each property
    /// (e.g. Id) there is a Boolean property that has a similar name (e.g. IsIdSelected)
    /// this Boolean property will be bound to the relevant DataGridCell.IsSelected
    /// property to indicate whether the cell representing this property were selected
    /// or not. In other words if you want to know the selected properties at any moment
    /// you just need to iterate through the employees collection, and examine each
    /// Boolean property for each property :D
    /// </summary>
    public class Employee
    {
        public int? Id { get; set; }
        public bool IsIdSelected { get; set; }
    
        public string Name { get; set; }
        public bool IsNameSelected { get; set; }
    
        public string Address { get; set; }
        public bool IsAddressSelected { get; set; }
    }
    

    背后的代码:

    using System.Collections.ObjectModel;
    using System.Windows;
    
    namespace CellSelection
    {
        public partial class MainWindow : Window
        {
            /// <summary>
            /// The DataGrid will be bound to this collection
            /// </summary>
            private ObservableCollection<Employee> _collection;
    
            public MainWindow()
            {
                InitializeComponent();
    
                // Initialize the employees collection with some test data
                _collection =
                    new ObservableCollection<Employee>
                        {
                            new Employee {Id = 1, Name = "Mohammed A. Fadil", Address = "..."},
                            new Employee {Id = 485, Name = "Khalid Zein", Address = "..."},
                            new Employee {Id = 64, Name = "Ahmed Mubarak", Address = "..."},
                            new Employee {Id = 364, Name = "Ali Ebraheim", Address = "..."},
                        };
    
                DataContext = _collection;
            }
    
            private void OnExportButtonClick(object sender, RoutedEventArgs e)
            {
                // Now, concatinate all the selected cells
                var str = string.Empty;
                foreach (var emp in _collection)
                {
                    if (emp.IsIdSelected)
                        str += string.Format("{0}, ", emp.Id);
    
                    if (emp.IsNameSelected)
                        str += string.Format("{0}, ", emp.Name);
    
                    if (emp.IsAddressSelected)
                        str += string.Format("{0}", emp.Address);
    
                    str += "\n";
                }
                // Instead of displaying this message you could export these cells to Excel
                // in the format you need.
                MessageBox.Show(str);
            }
        }
    }
    

    XAML 代码:

    <Window x:Class="CellSelection.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">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="275*" />
                <RowDefinition Height="36*" />
            </Grid.RowDefinitions>
            <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False"
                      SelectionMode="Extended" SelectionUnit="CellOrRowHeader">
                <DataGrid.Columns>
    
                    <DataGridTextColumn Header="Id" Binding="{Binding Id}">
                        <DataGridTextColumn.CellStyle>
                            <Style TargetType="DataGridCell">
                                <Setter Property="IsSelected">
                                    <Setter.Value>
                                        <Binding Path="IsIdSelected" Mode="TwoWay"
                                                 UpdateSourceTrigger="PropertyChanged"/>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridTextColumn.CellStyle>
                    </DataGridTextColumn>
    
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}">
                        <DataGridTextColumn.CellStyle>
                            <Style TargetType="DataGridCell">
                                <Setter Property="IsSelected">
                                    <Setter.Value>
                                        <Binding Path="IsNameSelected" Mode="TwoWay"
                                                 UpdateSourceTrigger="PropertyChanged"/>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridTextColumn.CellStyle>
                    </DataGridTextColumn>
    
                    <DataGridTextColumn Header="Address" Binding="{Binding Address}">
                        <DataGridTextColumn.CellStyle>
                            <Style TargetType="DataGridCell">
                                <Setter Property="IsSelected">
                                    <Setter.Value>
                                        <Binding Path="IsAddressSelected" Mode="TwoWay"
                                                 UpdateSourceTrigger="PropertyChanged"/>
                                    </Setter.Value>
                                </Setter>
                            </Style>
                        </DataGridTextColumn.CellStyle>
                    </DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
            <Button Content="Export Selection" Grid.Row="1" HorizontalAlignment="Right"
                    Click="OnExportButtonClick" Margin="5"/>
        </Grid>
    </Window>
    

    请注意,对于每个DataGrid 列,您必须添加一个CellStyle,它将每个指定布尔属性的列绑定到它的DataGridCell.IsSelected 属性,将此绑定模式设置为Mode="TwoWay" 以支持以编程方式选择单元格(在这种情况下,您必须在 Employee 类上实现 INotifyPropertyChanged

    使用此解决方案,您不再需要帮助函数,也不再需要访问 DataGrid 实际单元格,只需遍历您的集合,确定选定的属性并根据需要处理它们。

    【讨论】:

      【解决方案2】:

      我过去使用过剪贴板类,您可以在其中从网格中获取逗号分隔值,然后将其保存为 CSV,然后从 Excel 中打开它。我想这可能取决于您使用哪种网格控制

      MSDN On Clipboard

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-26
        • 2020-03-10
        相关资源
        最近更新 更多