[WIN]從型別'DataRowView'至型別'String'的轉換是無效的。

[WIN]從型別'DataRowView'至型別'String'的轉換是無效的。

今天幫同事查「從型別'DataRowView'至型別'String'的轉換是無效的。(無法將型別 'System.Data.DataRowView' 的物件轉換為型別 'System.String'。)」的錯誤。

image

發現寫在ComboBox的SelectedIndexChanged事件中取出ComboBox的SelectedValue轉成字串的值,會出現以上的錯誤! 在別的地方則OK。

看一下「呼叫堆疊」才發現,ComboBox設定DataSource後,會引發它的SelectedIndexChanged事件,而這時ComboBox的ValueMember還沒有指定,所以SelectedValue就會是DataRowView。

image

記得之前在測試checkedListBox Bind資料時,需要先設定DataSource呀! (請參考:[WIN]checkedListBox Bind資料要注意的地方!)

沒想到ComboBox 先設定DataSource + SelectedIndexChanged事件 + 存取ComboBox的SelectedValue值,居然會變成DataRowView。

於是ComboBox要先設定ValueMember。不過,這樣不就跟設定checkedListBox的順序不同了!

嗯~~~那如果在checkedListBox的SelectedIndexChanged事件中,去存取ComboBox的SelectedValue值,會不會也是一樣的問題呢?

哈,真是出現一樣的錯誤!

image

好吧,那就改成以下的順序
1.ValueMember
2.DataSource
3.DisplayMember

測試起來,目前都還OK!

程式如下,請先拉一個Button、一個ComboBox及一個checkedListBox。


private void button1_Click(object sender, EventArgs e)
{
    DataTable dtResult = new DataTable();
    dtResult.Columns.Add("d1", Type.GetType("System.String"));
    dtResult.Columns.Add("d2", Type.GetType("System.String"));
    dtResult.Rows.Add("d1v1", "d2v1");
    dtResult.Rows.Add("d1v2", "d2v2");
    dtResult.Rows.Add("d1v3", "d2v3");

    comboBox1.ValueMember = "d2";
    comboBox1.DataSource = dtResult;
    comboBox1.DisplayMember = "d1";

    checkedListBox1.ValueMember = "d2";
    checkedListBox1.DataSource = dtResult;
    checkedListBox1.DisplayMember = "d1";
}

private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    MessageBox.Show((string)checkedListBox1.SelectedValue);
}


private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    MessageBox.Show((string)comboBox1.SelectedValue);
}

 

 

使用VS2003測試了一下,發現如果先設定checkedListBox的DisplayMember屬性,再設定DataSource,Item的Text並不會變成System.Data.DataRowView。
目前這個問題只發生在.NET 2.0以上的Windows Form。 Code如下,

DataTable dtResult = new DataTable();
dtResult.Columns.Add("d1", Type.GetType("System.String"));
dtResult.Columns.Add("d2", Type.GetType("System.String"));
dtResult.Rows.Add(new string[] {"d1v1", "d2v1"});

dtResult.Rows.Add(new string[] {"d1v2", "d2v2"});
dtResult.Rows.Add(new string[] {"d1v3", "d2v3"});


checkedListBox1.ValueMember = "d2";
checkedListBox1.DisplayMember = "d1";
checkedListBox1.DataSource = dtResult;

 

所以就填了問題單回報給Microsoft。有興趣的人可以關注一下哦!
Why checkedListBox DisplayMember property should assign after DataSource property in .NET 2~4.5?

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^