WinForms:ListBox项更新不区分大小写?

时间:2011-09-22 17:13:51

标签: c# winforms .net-3.5 listbox

我有一个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控件的内部问题,特别是它决定(不)更新项目的方式,如果其字符串表示形式等同于新值,忽略案例差异。据我所知,这是硬编码到控件中,无法覆盖它。

3 个答案:

答案 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");

希望这有帮助。