Там может быть лучший способ добиться этого, я сейчас просто играю, пытаясь найти лучший способ выполнить определенную задачу.
У меня есть С# Winform с DataGridView и Детали в той же форме. Независимо, это отлично работает, и я могу просматривать записи и использовать инструменты в меню, которое отображается вверху. Я добавил combobox в named combobox1, и я хочу заполнить его значениями из таблицы SQL, которая выглядит так (есть дополнительные поля, такие как Site_Address, Site_PhoneNumber и т.д., Которые я удалил для упрощения):
Site_ID Client_ID Site_Display_Name
1 3 Microsoft
2 2 Google
3 1 Amazon
Мне нужно, чтобы displaymember был Site_Display_Name, но фактическое значение было Site_ID. Когда выполняется независимо, Combobox1 заполняется, если я прокомментирую эту строку
sitesBindingSource.Filter = "Site_ID = " + comboBox1.SelectedItem + " ";
Идея вышеприведенной строки заключается в том, что при изменении combobox она обновляет значение datagrid/details, которое находится в форме. Когда я включаю код, я получаю это исключение:
System.Data.EvaluateException was unhandled by user code
HResult=-2146232032
Message=Cannot find column [System.Data.DataRowView].
Source=System.Data
StackTrace:
at System.Data.NameNode.Bind(DataTable table, List'1 list)
at System.Data.BinaryNode.Bind(DataTable table, List'1 list)
at System.Data.DataExpression.Bind(DataTable table)
at System.Data.DataExpression..ctor(DataTable table, String expression, Type type)
at System.Data.DataView.set_RowFilter(String value)
at System.Data.DataView.System.ComponentModel.IBindingListView.set_Filter(String value)
at System.Windows.Forms.BindingSource.set_InnerListFilter(String value)
at System.Windows.Forms.BindingSource.set_Filter(String value)
at ImpactMessAround2.Form1.comboBox1_SelectedIndexChanged(Object sender, EventArgs e) in c:\Users\Gavin\Documents\Visual Studio 2013\Projects\ImpactMessAround2\ImpactMessAround2\Form1.cs:line 46
at System.Windows.Forms.ComboBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ComboBox.set_SelectedIndex(Int32 value)
at System.Windows.Forms.ComboBox.RefreshItems()
at System.Windows.Forms.ComboBox.OnDataSourceChanged(EventArgs e)
at System.Windows.Forms.ListControl.SetDataConnection(Object newDataSource, BindingMemberInfo newDisplayMember, Boolean force)
at System.Windows.Forms.ListControl.set_DataSource(Object value)
InnerException:
Код выглядит следующим образом:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void sitesBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
this.Validate();
this.sitesBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.gavin_TestDataSet);
}
private void Form1_Load(object sender, EventArgs e)
{
// TODO: This line of code loads data into the 'gavin_TestDataSet.Sites' table. You can move, or remove it, as needed.
this.sitesTableAdapter.Fill(this.gavin_TestDataSet.Sites);
SqlConnection mycon = new SqlConnection("Data Source=REDACTED;Initial Catalog=Gavin_Test;Persist Security Info=True;User ID=sa;Password=REDACTED");
SqlDataAdapter da = new SqlDataAdapter("select Site_ID, Site_Display_Name from Sites", mycon);
DataSet ds = new DataSet();
da.Fill(ds); mycon.Close();
comboBox1.DataSource = ds.Tables[0];
comboBox1.DisplayMember = "Site_Display_Name";
comboBox1.ValueMember = "Site_ID";
comboBox1.SelectedIndex = -1;
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
sitesBindingSource.Filter = "Site_ID = " + comboBox1.SelectedValue;
}
}
}
Новая ошибка с 21/07/2014
System.Data.EvaluateException was unhandled by user code
HResult=-2146232032
Message=Cannot perform '=' operation on System.Int32 and System.String.
Source=System.Data
StackTrace:
at System.Data.BinaryNode.BinaryCompare(Object vLeft, Object vRight, StorageType resultType, Int32 op, CompareInfo comparer)
at System.Data.BinaryNode.EvalBinaryOp(Int32 op, ExpressionNode left, ExpressionNode right, DataRow row, DataRowVersion version, Int32[] recordNos)
at System.Data.BinaryNode.Eval(DataRow row, DataRowVersion version)
at System.Data.DataExpression.Invoke(DataRow row, DataRowVersion version)
at System.Data.Index.AcceptRecord(Int32 record, IFilter filter)
at System.Data.Index.InitRecords(IFilter filter)
at System.Data.Index..ctor(DataTable table, IndexField[] indexFields, Comparison'1 comparison, DataViewRowState recordStates, IFilter rowFilter)
at System.Data.DataTable.GetIndex(IndexField[] indexDesc, DataViewRowState recordStates, IFilter rowFilter)
at System.Data.DataView.UpdateIndex(Boolean force, Boolean fireEvent)
at System.Data.DataView.UpdateIndex(Boolean force)
at System.Data.DataView.SetIndex2(String newSort, DataViewRowState newRowStates, IFilter newRowFilter, Boolean fireEvent)
at System.Data.DataView.SetIndex(String newSort, DataViewRowState newRowStates, IFilter newRowFilter)
at System.Data.DataView.set_RowFilter(String value)
at System.Data.DataView.System.ComponentModel.IBindingListView.set_Filter(String value)
at System.Windows.Forms.BindingSource.set_InnerListFilter(String value)
at System.Windows.Forms.BindingSource.set_Filter(String value)
at ImpactMessAround2.Form1.comboBox1_SelectedIndexChanged(Object sender, EventArgs e) in c:\Users\Gavin\Documents\Visual Studio 2013\Projects\ImpactMessAround2\ImpactMessAround2\Form1.cs:line 46
at System.Windows.Forms.ComboBox.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.ComboBox.set_SelectedIndex(Int32 value)
at System.Windows.Forms.ComboBox.RefreshItems()
at System.Windows.Forms.ComboBox.OnDataSourceChanged(EventArgs e)
at System.Windows.Forms.ListControl.SetDataConnection(Object newDataSource, BindingMemberInfo newDisplayMember, Boolean force)
at System.Windows.Forms.ListControl.set_DataSource(Object value)
InnerException:
Попробуй это:
Измените свой код:
comboBox1.DataSource = ds.Tables[0]; comboBox1.DisplayMember = "Site_Display_Name"; comboBox1.ValueMember = "Site_ID"; comboBox1.SelectedIndex = -1;
К этому:
comboBox1.DisplayMember = "Site_Display_Name";
comboBox1.ValueMember = "Site_ID";
comboBox1.DataSource = ds.Tables[0];
comboBox1.SelectedIndex = -1;
Jmcilhinney прав, но причина, по которой это правильно, может быть более понятным, если код был отформатирован несколько иначе.
sitesBindingSource.Filter = string.format("Site_ID = '{0}'", comboBox1.SelectedValue);
Ошибка, как сказал Jmcilhinney, заключается в том, что она вызывает ToString() в DataRowView в попытке получить значение фильтра строк. Я бы рекомендовал использовать string.format, как я сделал выше, для любого типа фильтра на основе строк, поскольку он делает то, что вы пытаетесь фильтровать, и как вы фильтруете его гораздо читабельнее.
Если это не сработает, какое новое сообщение об ошибке (как вы должны получить совершенно другую ошибку)? Какова ценность comboBox1.SelectedValue незадолго до того, как будет выбрано исключение?
Вы привязываете DataTable
к ComboBox
поэтому каждый элемент будет DataRowView
. Эта строка:
sitesBindingSource.Filter = "Site_ID = " + comboBox1.SelectedItem + " ";
пытается объединить DataRowView
со строкой. Если вы хотите выбрать значение Site_ID, вы должны использовать SelectedValue
, а не SelectedItem
. Это весь смысл установки ValueMember
.
Кстати, какая точка конкатенации строки, содержащей единственное пространство в конце этого? Здесь ничего нет. Не делай этого.