【问题标题】:Get cell values from DataGrid从 DataGrid 获取单元格值
【发布时间】:2018-07-10 14:16:13
【问题描述】:

我有一个 DataGrid,其中填充了来自连接的数据。

private void GetTeamData()
{
    DataContext dc = new DataContext(connString);
    Table<Team> tblLag = dc.GetTable<Team>();
    Table<Division> tblDivision = dc.GetTable<Division>();

    var teams = from team in tblLag
                join division in tblDivision on team.Division equals division.Id
                select new
                {
                    name = team.TeamName,
                    beliggenhet = team.Location,
                    arena = team.Arena,
                    division = division.Name
                };

    dgTeams.ItemsSource = teams;
}

我想从选定的行中获取数据并将其放置在不同的文本框中。经过大量令人沮丧的谷歌搜索和尝试后,我终于找到了一个可行的解决方案:

private void ShowSelectedTeam(Object sender, RoutedEventArgs args)
{
    GetDivisionNames();
    dgTeams.SelectionUnit = DataGridSelectionUnit.FullRow;
    Object selectedTeam = dgTeams.SelectedItem;

    List<PropertyInfo> props = new List<PropertyInfo>(selectedTeam.GetType().GetProperties());

    tbxTeam.Text = props[0].GetValue(selectedTeam, null).ToString();
    tbxBeliggenhet.Text = props[1].GetValue(selectedTeam, null).ToString();
    tbxArena.Text = props[2].GetValue(selectedTeam, null).ToString();
    cbxDivisions.Text = props[3].GetValue(selectedTeam, null).ToString();
}

问题在于,这是一种非常复杂的方法,可以做一些不应该那么困难的事情。对于更简单的代码的建议,我会很高兴。

【问题讨论】:

  • 创建一个包含 name、beliggenhet、arena 和 Division 属性的类型。

标签: c# wpf linq datagrid


【解决方案1】:

创建一个包含 name、beliggenhet、arena 和 Division 属性的类型:

public class YourType
{
    public string Name { get; set; }
    public string Beliggenhet { get; set; }
    public string Arena { get; set; }
    public string Division { get; set; }
}

ItemsSource 设置为IEnumerable&lt;YourType&gt;

var teams = from team in tblLag
                join division in tblDivision on team.Division equals division.Id
                select new YourType
                {
                    Name = team.TeamName,
                    Beliggenhet = team.Location,
                    Arena = team.Arena,
                    Division = division.Name
                };

并将SelectedItem 属性转换为您的类型:

YourType selectedTeam = dgTeams.SelectedItem as YourType;
if (selectedTeam != null)
{
    tbxTeam.Text = selectedTeam.Name;
    tbxBeliggenhet.Text = selectedTeam.Beliggenhet;
    ...
}

【讨论】:

  • 感谢您的回复,很清楚。但是,我有点不愿意为此目的创建一个类型。我不确定这会使代码整体不那么复杂。但我现在知道这些选项,所以我会一路考虑。
  • 然后您可以使用dynamic 关键字,但您会失去编译时安全性。你为什么不愿意创建一个类型......!?您当前的解决方案有效,但您认为它“复杂”。创建一个类型可以解决这个问题。
  • 你试过我的代码了吗?如果您不想出现运行时错误,您应该创建一个编译时已知类型并尝试使用 as 运算符对其进行转换。
  • (昨天的更正评论)当谷歌搜索编译时安全时,我意识到这是一个好点。您说当前的解决方案有效。但是,在您建议的解决方案出现编译时错误的情况下,动态类型的代码会出现运行时错误,这不是真的吗?我的代码可能根本不会出错,但代码不会按预期工作?考虑到这一点,我认为最好按照您和 ASh 的建议创建一个类型。 – PellePetimeter 12 小时前
  • 是的,我会按照你和 Ash 的建议在 type 上创建。我认为这是明智的原因是因为如果填充网格的代码和从网格获取数据的代码之间存在任何不一致,将导致编译时错误,这比运行时错误或只是程序要好停止正常工作。
【解决方案2】:

获取选中项属性非常复杂,因为选中项具有匿名类型。

创建一个类型

public class TeamViewModel
{
    public string name { get; set; }
    public string beliggenhet { get; set; }
    public string arena { get; set; }
    public string division { get; set; }
}

在填充 ItemsSource 时创建该类型的对象:

var teams = from team in tblLag
            join division in tblDivision on team.Division equals division.Id
            select new TeamViewModel
            {
                name = team.TeamName,
                beliggenhet = team.Location,
                arena = team.Arena,
                division = division.Name
            };

您将能够将 SelectedItem 转换为具体类型并读取属性而无需反射:

private void ShowSelectedTeam(Object sender, RoutedEventArgs args)
{
    GetDivisionNames();
    dgTeams.SelectionUnit = DataGridSelectionUnit.FullRow;
    var selectedTeam = dgTeams.SelectedItem as TeamViewModel;

    if (selectedTeam == null) return;

    tbxTeam.Text = selectedTeam.name;
    tbxBeliggenhet.Text = selectedTeam.beliggenhet;
    tbxArena.Text = selectedTeam.arena;
    cbxDivisions.Text = selectedTeam.division;
}

如果您仍想继续使用匿名类型,可以使用dynamic 类型读取值(仅ShowSelectedTeam 方法更改):

private void ShowSelectedTeam(Object sender, RoutedEventArgs args)
{
    GetDivisionNames();
    dgTeams.SelectionUnit = DataGridSelectionUnit.FullRow;
    dynamic selectedTeam = dgTeams.SelectedItem;

    if (selectedTeam == null) return;

    tbxTeam.Text = selectedTeam.name.ToString();
    tbxBeliggenhet.Text = selectedTeam.beliggenhet.ToString();
    tbxArena.Text = selectedTeam.arena.ToString();
    cbxDivisions.Text = selectedTeam.division.ToString();
}

【讨论】:

  • 感谢您的回复,很清楚。但是,我有点不愿意为此目的创建一个类型。我不确定这会使代码整体不那么复杂。但我现在知道这些选项,所以我会一路考虑。
  • @PellePetimeter,不客气。考虑接受您收到的答案之一
  • 但是在考虑 mm8 指出的关于编译时安全的内容时,我认为最好创建一个类型,正如您和 mm8 最初建议的那样。
猜你喜欢
  • 1970-01-01
  • 2011-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-24
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
相关资源
最近更新 更多