我有一个Windows表单ListBox
数据绑定到BindingList
业务对象。 ListBox的显示属性是表示业务对象名称的字符串。我有一个TextBox
没有数据绑定到name属性,而是在ListBox的选定索引更改时填充,而TextBox在验证时设置业务对象的name属性,然后使用BindingList.ResetItem
通知BindingList
的绑定控件(ListBox)在用户更改TextBox的文本值时自行更新。
除非名称更改只是大小写的变化(即“名称”改为“名称”),否则这种方法很有效,在这种情况下,ListBox
不会更新(它仍然会显示“名称”,甚至虽然底层业务对象的name属性的值是“Name”)。
任何人都可以解释为什么会发生这种情况以及我应该做些什么呢?我目前的解决方法是使用BindingList.ResetBindings
,这对我有用,但对于较大的数据集可能无法接受。
2011年9月27日更新:添加了一个简单的代码示例,可以为我重现问题。这是使用INotifyPropertyChanged
并将文本框绑定到绑定列表。基于How do I make a ListBox refresh its item text?
using System;
using System.ComponentModel;
using System.Windows.Forms;
namespace WinformsDataBindingListBoxTextBoxTest
{
public partial class Form1 : Form
{
private BindingList<Employee> _employees;
private ListBox lstEmployees;
private TextBox txtId;
private TextBox txtName;
private Button btnRemove;
public Form1()
{
InitializeComponent();
FlowLayoutPanel layout = new FlowLayoutPanel();
layout.Dock = DockStyle.Fill;
Controls.Add(layout);
lstEmployees = new ListBox();
layout.Controls.Add(lstEmployees);
txtId = new TextBox();
layout.Controls.Add(txtId);
txtName = new TextBox();
layout.Controls.Add(txtName);
btnRemove = new Button();
btnRemove.Click += btnRemove_Click;
btnRemove.Text = "Remove";
layout.Controls.Add(btnRemove);
Load += new EventHandler(Form1_Load);
}
private void Form1_Load(object sender, EventArgs e)
{
_employees = new BindingList<Employee>();
for (int i = 0; i < 10; i++)
{
_employees.Add(new Employee() { Id = i, Name = "Employee " + i.ToString() });
}
lstEmployees.DisplayMember = "Name";
lstEmployees.DataSource = _employees;
txtId.DataBindings.Add("Text", _employees, "Id");
txtName.DataBindings.Add("Text", _employees, "Name");
}
private void btnRemove_Click(object sender, EventArgs e)
{
Employee selectedEmployee = (Employee)lstEmployees.SelectedItem;
if (selectedEmployee != null)
{
_employees.Remove(selectedEmployee);
}
}
}
public class Employee : INotifyPropertyChanged
{
private string name;
private int id;
public string Name
{
get { return name; }
set
{
name = value;
OnPropertyChanged("Name");
}
}
public int Id
{
get { return id; }
set
{
id = value;
OnPropertyChanged("Id");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
#endregion
}
}
更新9/28/2011:问题似乎是ListBox控件的内部问题,特别是它决定(不)更新项目的方式,如果其字符串表示形式等同于新值,忽略案例差异。据我所知,这是硬编码到控件中,无法覆盖它。
答案 0 :(得分:1)
答案 1 :(得分:0)
我希望这个概念能够帮助您解决问题
我有一个TextBox,用户输入与字符串“Name”进行比较。我的按钮点击事件是:
private void btn_Click(object sender, EventArgs e)
{
if(txt.Text == "Name")
MessageBox.Show("Value is Same");
}
如果在文本框中输入“name”,则条件为false。如果在文本框中键入“名称”类型,则条件为true。 现在尝试更改btn点击:
using System.Globalization;
private void btn_Click(object sender, EventArgs e)
{
TextInfo ChangeCase = new CultureInfo("en-US", false).TextInfo;
string newText = ChangeCase.ToTitleCase(txt.Text);
if (newText == "Name")
MessageBox.Show("Value is Same");
}
现在键入“name”或“Name”条件为true。 请记住,它只会对所提供的字符串的第一个字母进行资格化。 “我的名字”将输出为“我的名字”。
如果你的情况如此:
if(txt.Text == "name")
MessageBox.Show(Value is Same);
然后你可以试试像
这样的东西string newText = (txt.Text).ToLower();
if(newText == "name")
MessageBox.Show(Value is Same);
此处提供的字符串将始终以小写字母输出。 希望它有所帮助。
答案 2 :(得分:0)
这实际上与重命名文件或目录时的问题完全相同,只是大小写不同。我建议我之前找到的同样的解决办法:
if (oldValue.ToUpper() == newValue.ToUpper()){
ListBox1.Items[i] = newValue + "_tmp"; // only adding stuff to force an update
ListBox1.Items[i] = newValue; // now the new value is displayed, even only case has changed
}
现在针对您的问题,我建议您尝试检查setter是否仅以大写/小写(a.ToUpper()== b.ToUpper())更改值。如果为真,那么首先在预期的更改之前进行额外的更改,例如:
name = value + "_tmp";
OnPropertyChanged("Name");
name = value;
OnPropertyChanged("Name");
希望这有帮助。