【问题标题】:How can I bind an SQL Query to a DataGrid?如何将 SQL 查询绑定到 DataGrid?
【发布时间】:2016-04-22 12:19:18
【问题描述】:
    <DataGrid Name="getEmployees" ItemsSource="{Binding}">
        <DataGrid.Columns>
            <DataGridCheckBoxColumn />
            <DataGridTextColumn />
        </DataGrid.Columns>
    </DataGrid>

这是我的数据网格

这是我的代码隐藏

    public ViewMyProxy()
    {
        InitializeComponent();            
        FillDataGrid();
    }

    private void FillDataGrid()
    {

        var connectionString = ConfigurationManager.ConnectionStrings["MyDatabase"].ConnectionString;
        string CmdString = string.Empty;
        using (OleDbConnection con = new OleDbConnection(connectionString))
        {
            CmdString = "SELECT proxyFor, enabled FROM accesscontrol WHERE currentlyLoggedOnUser = '" + Environment.UserName + "'";
            OleDbCommand cmd = new OleDbCommand(CmdString, con);
            OleDbDataAdapter sda = new OleDbDataAdapter(cmd);
            DataTable dt = new DataTable("Employee");
            sda.Fill(dt);
            getEmployees.ItemsSource = dt.DefaultView;
        }
    }

我的问题

  1. 有没有办法加载 SQL 查询并将其直接与 DataGrid 绑定?
  2. 启用的列是一个数字字段(0 = false 和 1 = true),我们可以将它绑定到 DataGridCheckBoxColumn 吗?基本上,当用户取消选中某个框时,我想尽快更新表格。

使用代码隐藏,当我的 WPF 加载时,我最终得到 3 列而不是 2。我希望第一列是复选框(从 SQL 查询启用),proxyFor 是我想要的字符串第二栏。

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    您需要将DataGrid.AutoGenerateColumns 设置为False,以防止它自动生成列。然后,您需要显式绑定您自己定义的列。 DataGridCheckBoxColumn 和 DataGridTextColumn 都具有您可以设置的其他属性,以进一步自定义您在网格中看到的内容。

    <DataGrid 
        Name="getEmployees" 
        AutoGenerateColumns="False"
        >
        <DataGrid.Columns>
            <DataGridCheckBoxColumn 
                Binding="{Binding enabled}"
                Header="Enabled"
                />
            <DataGridTextColumn 
                Binding="{Binding proxyFor}"
                Header="Proxy For"
                />
        </DataGrid.Columns>
    </DataGrid>
    

    如果复选框列不能按您想要的方式工作,您可以尝试编写 value converter 来在您的整数和布尔值之间进行转换。

    XAML(部分):

            <DataGridCheckBoxColumn 
                xmlns:myconv="clr-namespace:MyProject.Converters"
                Binding="{Binding enabled, Converter={myconv:IntToBool}}"
                />
    

    C#

    namespace MyProject.Converters
    {
        public class IntToBool : MarkupExtension, IValueConverter
        {
            public override object ProvideValue(IServiceProvider serviceProvider) => this;
    
            public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return ((int)value) != 0;
            }
    
            public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return ((bool)value) ? 1 : 0;
            }
        }
    }
    

    如果这不起作用,您将需要改用DataGridTemplateColumn,这将使您有更多的能力来控制列的外观及其工作方式。

    在回答您的第一个问题“有没有办法加载 SQL 查询并将其直接与 DataGrid 绑定?”时,我不确定这到底是什么意思:您问是否可以分配 SQL 字符串到DataGrid 的某些属性并让它执行查询并自行填充?不,如果你真的想的话,你可以写一个附加的属性来做到这一点。那可能很有趣。

    还有一点,你没有问,但应该提到:

    CmdString = "SELECT proxyFor, enabled FROM accesscontrol WHERE currentlyLoggedOnUser = '" 
        + Environment.UserName + "'";
    

    如果您已经知道这是不好的做法,并且您打算在代码正常运行后更换它,那么您不需要听到这个,但如果不是这样,您真的应该养成绝对的习惯使用参数:

    CmdString = "SELECT proxyFor, enabled FROM accesscontrol WHERE "
        + "currentlyLoggedOnUser = @userName";
    
    OleDbCommand cmd = new OleDbCommand(CmdString, con);
    
    cmd.Parameters.AddWithValue("userName", Environment.UserName);
    

    如果somebody has a single quote in his user name 怎么办?这有可能发生。而且,如果您在面向外部的代码中使用简单的 SQL 字符串串联,您将允许地球上的任何人在您的数据库中运行任意 SQL。

    为什么在 XAML 中有ItemsSource="{Binding}"?这会将 DataGrid 的 DataContext 绑定到 ItemsSource。如果您的视图具有视图模型,则该 DataContext 应该是视图模型;否则,它可能为空。无论如何,你在代码中分配了其他东西。

    【讨论】:

    • 我不知道为什么我有它。有人告诉我把它放在那里,XAML 包括 ItemsSource="{Binding Mode=TwoWay, Path=accesscontrol}"
    • @softwareisfun 好吧,通常你会将查询结果放在视图模型上的ObservableCollection 中,然后像这样绑定它:ItemsSource="{Binding WhateverICalledMyResultsCollection}"。这是推荐的,但我认为在您让网格以这种方式工作之前,我们不需要去那里。
    • 如果我们想将复选框的状态从启用更改为禁用,我们将如何更新记录?
    • @softwareisfun 您的意思是来自视图模型还是来自代码隐藏?为此,您可以 (a) 保留对 DataTable 的引用并对其进行导航,或者 (b) 不使用 DataTable,而是使用 POCO 类的 ObservableCollection,该类具有与 DB 记录和实现相同的两个字段INotifyPropertyChanged。您将阅读数据库,为每条记录创建一个新的 POCO 类实例,然后当您想要更改字段值时,您可以通过 ObservableCollection 中的实例来完成。要保存回 DB,您必须编写一个循环来处理 POCO。
    • 不是 SQLServer 的 POCO。我正在使用 MS Access。我在网上找了POCO Generator和POCO,发现很多关于SQL SERVER的文章。
    猜你喜欢
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 2011-01-08
    • 1970-01-01
    • 2011-10-12
    • 2014-01-13
    • 1970-01-01
    • 2014-08-23
    相关资源
    最近更新 更多