3

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

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

4

2 回答 2

2

假设DataGrid显示员工信息,我们存储每个员工的Id,NameAddress。让我们为每个员工属性(例如Idand IsIdSelected, Nameand IsNameSelected)添加一个额外的布尔属性,这个布尔属性将绑定到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"为以支持以编程方式选择单元格(在这种情况下,您必须INotifyPropertyChangedEmployee类上实现)。

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

于 2011-04-06T19:13:53.653 回答
0

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

剪贴板上的 MSDN

于 2011-04-06T15:43:03.407 回答