简体   繁体   中英

Static combobox within a datagrid in WPF, but have the Selected Value set by SQL

I am trying to use a static list of asset status codes in a combobox, but use an SQL query to pull the appropriate status from an SQL server and use it as the selected value.

For example, the combobox, would have "Active", "Returned" or "Repair Depot" set, but it would obtain the selected value via the database table Assets which has a field in it called Status.

I am having an issue populating the combobox. No errors, but no data either.

The XAML:

<Window x:Class="Test_Personnel.Dialogs.WinAssets"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Test_Personnel.Dialogs"
    mc:Ignorable="d"
    Title="Assets" Height="450" Width="800" Loaded="AssetsLoad">
<Grid Margin="0,10,0,0">
    <DataGrid Name="AssetGrid" HorizontalAlignment="Left" Margin="31,57,0,0" VerticalAlignment="Top" ItemsSource="{Binding Path=Assets}" AutoGenerateColumns="False" AlternatingRowBackground="LightBlue" RenderTransformOrigin="0.534,2.99">
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="Status" ItemsSource="{Binding Status}"/>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button x:Name="Save" Content="Save" Click="Button_Assets_Save_Click" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Binding="{Binding Path=AssetType, UpdateSourceTrigger=LostFocus}" Header="Type" Width="auto"/>
            <DataGridTextColumn Binding="{Binding Path=AssetNo, UpdateSourceTrigger=LostFocus}" Header="Asset Number" Width="auto"/>
            <DataGridTextColumn Binding="{Binding Path=AssetSerialNo, UpdateSourceTrigger=LostFocus}" Header="Serial No" Width="auto"/>
            <DataGridTextColumn Binding="{Binding Path=AssetPhoneNo, UpdateSourceTrigger=LostFocus}" Header="Phone No" Width="auto"/>
        </DataGrid.Columns>
    </DataGrid>
    <ComboBox Name="cmbEmployee" SelectedValuePath="Tag" SelectionChanged="CmbEmployee_Changed" HorizontalAlignment="Left" Margin="31,30,0,0" VerticalAlignment="Top" Width="193"/>
</Grid>

The code behind:

/// <summary>
/// Interaction logic for WinAssets.xaml
/// </summary>
public partial class WinAssets : Window
{

    // Create a new string to store the employee ID so we can use it later
    public String strEmpID
    { get; set; }

    // Class for the status portion of the combobox
    public class Option
    {
        public int OptionId { get; set; }
        public string StatusText { get; set; }
    }

    public class BoundObject
    {
        public List<Option> cmbStatus { get; set; }
    }

    readonly SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder
    {
        DataSource = "",
        UserID = "",
        Password = "",
        InitialCatalog = "Personnel",
        PersistSecurityInfo = false,
        MultipleActiveResultSets = false,
        Encrypt = true,
        TrustServerCertificate = false,
        ConnectTimeout = 30
    };

    public WinAssets()
    {
        InitializeComponent();

    }

    // assign the employee ID to the object
    public WinAssets(String strempID):this()
    { this.strEmpID = strempID;
    }


private void AssetsLoad(object sender, RoutedEventArgs e)
    {
        int j = 0;

        SqlConnection connection = new SqlConnection(builder.ConnectionString);
        connection.Open();

        // Create daPersonnel adapter to get employee information so we can use it to select data in ComboBox
        SqlDataAdapter daPersonnel = new SqlDataAdapter("SELECT * FROM Employee", connection);
        DataTable dtPersonnel = new DataTable();
        daPersonnel.Fill(dtPersonnel);

        ComboBoxItem item = new ComboBoxItem();
        item.Content = "All";
        item.Tag = "0";
        cmbEmployee.Items.Add(item);
        for (int i = 0; i < dtPersonnel.Rows.Count; i++)
        {
            ComboBoxItem item1 = new ComboBoxItem();
            item1.Content = dtPersonnel.Rows[i]["LastName"].ToString() + ", " + dtPersonnel.Rows[i]["FirstName"].ToString();
            item1.Tag = dtPersonnel.Rows[i]["EmployeeID"].ToString();
            cmbEmployee.Items.Add(item1);

            //if the string strEmpId is set, then someone requested it via the MainWindow, so get the row (j) corresponding to the appropriate Employee
            if (dtPersonnel.Rows[i]["EmployeeId"].ToString() == strEmpID)
            {
                j = i;
            }
        }

        if (strEmpID != null)
        {
            cmbEmployee.SelectedValue = dtPersonnel.Rows[j]["EmployeeId"].ToString();
        }

        StringBuilder sb = new StringBuilder();
        sb.Append("SELECT EmployeeID, Status, AssetType, AssetNo, AssetPhoneNo, AssetSerialNo FROM Assets WHERE EmployeeID = @strEmpID1;");
        String sql = sb.ToString();

        SqlCommand command = new SqlCommand(sql, connection);
        var strEmpIDparam = new SqlParameter("strEmpID1", SqlDbType.VarChar);
        strEmpIDparam.Value = strEmpID;
        command.Parameters.Add(strEmpIDparam);
        DataTable dt = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(command);
        adapter.Fill(dt);

        // Set status combobox to be selected to what is in the database
        var sOpts = new List<Option> { new Option { StatusText = "Active" }, new Option { StatusText = "Returned" }, new Option { StatusText = "Repair Depot" } };
        var list = new List<BoundObject> { new BoundObject { cmbStatus = sOpts } };

        //AssetGrid.ItemsSource = list;

        AssetGrid.ItemsSource = dt.DefaultView;
        AssetGrid.CanUserAddRows = false;

        daPersonnel.Dispose();
        adapter.Dispose();
        command.Dispose();
        connection.Close();
    }

    private void Filldatagrid()
    {

        int j = 0;

        SqlConnection connection = new SqlConnection(builder.ConnectionString);
        connection.Open();

        // Create daPersonnel adapter to get employee information so we can use it to select data in ComboBox
        SqlDataAdapter daPersonnel = new SqlDataAdapter("SELECT * FROM Employee", connection);
        DataTable dtPersonnel = new DataTable();
        daPersonnel.Fill(dtPersonnel);

        ComboBoxItem item = new ComboBoxItem();
        item.Content = "All";
        item.Tag = "0";
        cmbEmployee.Items.Add(item);
        for (int i = 0; i < dtPersonnel.Rows.Count; i++)
        {
            ComboBoxItem item1 = new ComboBoxItem();
            item1.Content = dtPersonnel.Rows[i]["LastName"].ToString() + ", " + dtPersonnel.Rows[i]["FirstName"].ToString();
            item1.Tag = dtPersonnel.Rows[i]["EmployeeID"].ToString();
            cmbEmployee.Items.Add(item1);

            //if the string strEmpId is set, then someone requested it via the MainWindow, so get the row (j) corresponding to the appropriate Employee
            if (dtPersonnel.Rows[i]["EmployeeId"].ToString() == strEmpID)
            {
                j = i;
            }
        }

        if (strEmpID != null)
        {
            cmbEmployee.SelectedValue = dtPersonnel.Rows[j]["EmployeeId"].ToString();
        }

        StringBuilder sb = new StringBuilder();
        sb.Append("SELECT EmployeeID, Status, AssetType, AssetNo, AssetPhoneNo, AssetSerialNo FROM Assets WHERE EmployeeID = @strEmpID1;");
        String sql = sb.ToString();

        SqlCommand command = new SqlCommand(sql, connection);
        var strEmpID1param = new SqlParameter("strEmpID1", SqlDbType.VarChar);
        strEmpID1param.Value = strEmpID;
        command.Parameters.Add(strEmpID1param);
        DataTable dt = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(command);
        adapter.Fill(dt);

        AssetGrid.ItemsSource = dt.DefaultView;
        AssetGrid.CanUserAddRows = false;

        daPersonnel.Dispose();
        adapter.Dispose();
        command.Dispose();
        connection.Close();

    }

    private void Button_Assets_Save_Click(object sender, RoutedEventArgs e)
    {

    }

    private void CmbEmployee_Changed(object sender, SelectionChangedEventArgs e)
    {

        strEmpID = (string)((ComboBoxItem) cmbEmployee.SelectedItem).Tag; //get value of combobox (the ID)
        int j = 0;

        SqlConnection connection = new SqlConnection(builder.ConnectionString);
        connection.Open();

        // Create daPersonnel adapter to get employee information so we can use it to select data in ComboBox
        SqlDataAdapter daPersonnel = new SqlDataAdapter("SELECT * FROM Employee", connection);
        DataTable dtPersonnel = new DataTable();
        daPersonnel.Fill(dtPersonnel);

        for (int i = 0; i < dtPersonnel.Rows.Count; i++)
        {

            //if the string strEmpId is set, then someone requested it via the MainWindow, so get the row (j) corresponding to the appropriate Employee
            if (dtPersonnel.Rows[i]["EmployeeId"].ToString() == strEmpID)
            {
                j = i;
            }
        }

        if (strEmpID != null)
        {
            cmbEmployee.SelectedValue = strEmpID;
        }

        StringBuilder sb = new StringBuilder();
        if (strEmpID == "0")
        {
            sb.Append("SELECT Employee.FirstName, Employee.LastName, Assets.EmployeeID, Assets.AssetType, Assets.AssetNo, Assets.AssetPhoneNo, Assets.AssetSerialNo, Assets.Status FROM Assets JOIN Employee ON Assets.EmployeeID = Employee.EmployeeId;");
            DataGridTextColumn textColumnFN = new DataGridTextColumn();
            AssetGrid.AutoGenerateColumns = false;
            textColumnFN.Header = "First Name";
            textColumnFN.Binding = new Binding("FirstName");
            AssetGrid.Columns.Add(textColumnFN);
            DataGridTextColumn textColumnLN = new DataGridTextColumn();
            textColumnLN.Header = "Last Name";
            textColumnLN.Binding = new Binding("LastName");
            AssetGrid.Columns.Add(textColumnLN);
        }
        else
        {
            // If AssetGrid has more than 4 columns than someone selected all, which needs FirstName, LastName, but now we don't need those
            if (AssetGrid.Columns.Count > 6)
            { 
                AssetGrid.Columns.RemoveAt(6);  // Remove First Name column
                AssetGrid.Columns.RemoveAt(6);  // Since we removed First Name column, Last Name Column is now column 6, remote it too.
            }
            sb.Append("SELECT EmployeeID, Status, AssetType, AssetNo, AssetPhoneNo, AssetSerialNo FROM Assets WHERE EmployeeID = @strEmpID1;");
        }

        String sql = sb.ToString();

        SqlCommand command = new SqlCommand(sql, connection);
        var strEmpID1param = new SqlParameter("strEmpID1", SqlDbType.VarChar);
        strEmpID1param.Value = strEmpID;
        command.Parameters.Add(strEmpID1param);
        DataTable dt = new DataTable();
        SqlDataAdapter adapter = new SqlDataAdapter(command);
        adapter.Fill(dt);

        AssetGrid.ItemsSource = dt.DefaultView;
        AssetGrid.CanUserAddRows = false;

        daPersonnel.Dispose();
        adapter.Dispose();
        command.Dispose();
        connection.Close();
    }

}

}

What I am mainly working on right now is the AssetsLoad. If I can get it to work on loading, I think I can handle the rest.

I cannot get the combobox to either load any of the static data or the datafrom the SQL server.

Thank you, in advance!

Image of broken combobox

I guess you are not familiar with WPF programming. I think you want to binding "Status" to ComboBoxColumn ItemsSsource.

<Window x:Class="Test_Personnel.Dialogs.WinAssets"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Test_Personnel.Dialogs"
    mc:Ignorable="d" x:Name="mainWnd"
    Title="Assets" Height="450" Width="800" Loaded="AssetsLoad">
<Grid Margin="0,10,0,0">
    <DataGrid Name="AssetGrid" HorizontalAlignment="Left" Margin="31,57,0,0" VerticalAlignment="Top" ItemsSource="{Binding Path=Assets}" AutoGenerateColumns="False" AlternatingRowBackground="LightBlue" RenderTransformOrigin="0.534,2.99">
        <DataGrid.Columns>
            <DataGridComboBoxColumn Header="Status" ItemsSource="{Binding Status,ElementName=MainWnd}" DisplayMemberPath="StatusText" />
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button x:Name="Save" Content="Save" Click="Button_Assets_Save_Click" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Binding="{Binding Path=AssetType, UpdateSourceTrigger=LostFocus}" Header="Type" Width="auto"/>
            <DataGridTextColumn Binding="{Binding Path=AssetNo, UpdateSourceTrigger=LostFocus}" Header="Asset Number" Width="auto"/>
            <DataGridTextColumn Binding="{Binding Path=AssetSerialNo, UpdateSourceTrigger=LostFocus}" Header="Serial No" Width="auto"/>
            <DataGridTextColumn Binding="{Binding Path=AssetPhoneNo, UpdateSourceTrigger=LostFocus}" Header="Phone No" Width="auto"/>
        </DataGrid.Columns>
    </DataGrid>
    <ComboBox Name="cmbEmployee" SelectedValuePath="Tag" SelectionChanged="CmbEmployee_Changed" HorizontalAlignment="Left" Margin="31,30,0,0" VerticalAlignment="Top" Width="193"/>
</Grid>

but your code doesn't have Status property. write it.

public List<Option> Status { get; set; }

rewrite init status.

Status = new List<Option> { new Option { StatusText = "Active" }, new Option { StatusText = "Returned" }, new Option { StatusText = "Repair Depot" } };

try it. Good Luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM