WinForms: обновления элемента ListBox не чувствительны к регистру? - PullRequest
3 голосов
/ 22 сентября 2011

У меня есть Windows Forms ListBox, привязанная к данным BindingList бизнес-объектов.Отображаемое свойство ListBox представляет собой строку, представляющую имя бизнес-объекта.У меня есть TextBox, который не привязан к данным для свойства name, но вместо этого заполняется при изменении выбранного индекса ListBox, а TextBox после проверки устанавливает свойство name бизнес-объекта, а затем использует BindingList.ResetItem для уведомления *Связанный элемент управления 1005 * (ListBox) обновляется, когда текстовое значение TextBox изменяется пользователем.

Это прекрасно работает, если только изменение имени не является изменением регистра (то есть «имя» на «Имя "), в этом случае ListBox не обновляется (оно по-прежнему говорит" имя ", хотя значением имени свойства базового бизнес-объекта является" Имя ").

Может кто-нибудь объяснитьпочему это происходит и что я должен делать вместо этого?Мой текущий обходной путь - использовать BindingList.ResetBindings, который может работать для меня, но может быть неприемлемым для больших наборов данных.

Обновление от 27.09.2011: Добавлен простой пример кода, который воспроизводитпроблема для меня.Это использует INotifyPropertyChanged и привязывает текстовое поле к списку привязок.На основе Как заставить ListBox обновить текст элемента?

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
    }
}

Обновление от 28.09.2011: Кажется, что проблема внутренняя в ListBoxуправление, а именно то, как он решает (не) обновить элемент, если его строковое представление эквивалентно новому значению, игнорируя различия регистра.Насколько я могу судить, это жестко запрограммировано в элементе управления без возможности его переопределить.

Ответы [ 3 ]

1 голос
/ 28 сентября 2011

Думаю, я нашел проблему:

0 голосов
/ 07 мая 2012

Это действительно та же проблема, что и при переименовании файлов или каталогов, в то время как отличается только регистр.Я предлагаю тот же обходной путь, который я нашел ранее:

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
}

Теперь для вашего вопроса я предлагаю вам попробовать проверить, меняет ли установщик значение только в нижнем / верхнем регистре (a.ToUpper) == b.ToUpper ()).Если это правда, то сначала дайте дополнительное изменение, перед предполагаемым изменением, что-то вроде:

name = value + "_tmp";
OnPropertyChanged("Name");
name = value;
OnPropertyChanged("Name");

Надеюсь, это поможет.

0 голосов
/ 23 сентября 2011

Я просто надеюсь, что эта концепция поможет вам решить вашу проблему

У меня есть TextBox, пользовательский ввод сравнивается со строкой "Имя".Мое событие нажатия кнопки:

private void btn_Click(object sender, EventArgs e)
{
  if(txt.Text == "Name")
     MessageBox.Show("Value is Same");
}

Если вы напишите «имя» в текстовом поле, условие будет ложным.Если вы введете «Имя» в текстовое поле, условие будет выполнено.Теперь попробуйте изменить btn click:

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");
}

, теперь вы вводите «имя» или «Имя», условие истинно.Помните, что это просто заглушит первую букву поставленной строки.«Мое имя» будет выведено как «Мое имя».

И если ваше состояние говорит:

if(txt.Text == "name")
   MessageBox.Show(Value is Same);

Тогда вы можете попробовать что-то вроде

string newText = (txt.Text).ToLower();
if(newText == "name")
   MessageBox.Show(Value is Same);

Здесьпредоставленная строка будет всегда выводиться в нижнем регистре.Надеюсь, это поможет.

...