Итерация по списку/массиву bool возвращает все ложные значения

#c# #list #winforms #boolean

Вопрос:

Я создаю это приложение Windows forms c#, в котором я могу загружать изображения из папки, выбирать некоторые из них, нажимая на их изображение, а затем копировать их в другую папку. До сих пор все казалось хорошим, но теперь я наткнулся на проблему. У меня есть 10 булов, которые представляют статус каждого изображения ( выбрано или не выбрано).

     public partial class Form1 : Form
{


    public bool selected1 = false;
    public bool selected2 = false;
    public bool selected3 = false;
    public bool selected4 = false;
    public bool selected5 = false;
    public bool selected6 = false;
    public bool selected7 = false;
    public bool selected8 = false;
    public bool selected9 = false;
    public bool selected10 = false;
 

это те самые болваны.
Затем я помещаю их в список ( я тоже тестировал массив).

 private List<bool> selectedBools = new List<bool>();
 

А затем я назначаю булы в список в общедоступной Форме1():

  selectedBools = new List<bool> { selected1, selected2, selected3, selected4, selected5, selected6, selected7, selected8, selected9, selected10 };
 

Каждый статус изображения контролируется этим фрагментом кода ( каждый щелчок picturebox_click имеет один и тот же код с измененными номерами).

  private void pictureBox2_Click_1(object sender, EventArgs e)
    {


        if (selected1 == false)
        {

            pctBox1.Image = null;


            selected1 = true;
            pctBox1.BackColor = Color.Red;
        }
        else if (selected1 == true)
        {
            selected1 = false;
            pctBox1.BackColor = Color.White;
            try
            {
                pctBox1.Image = Image.FromFile(filePaths[0   Page * 10]); // refresh image
            }
            catch
            {

            }

        }

    }
 

Затем, когда я нажимаю, чтобы изменить «Страницу» ( которая просто перемещает каждое изображение на 10), я снова устанавливаю все булы в значение false.
Проблема в том, что я хочу «загрузить» эти изображения в папку ( просто скопируйте выбранные там).:

  private void UploadAllButton_Click(object sender, EventArgs e)
    {
        Console.WriteLine(selected1.ToString()   selected2   selected3   selected4   selected5   selected6   selected7   selected8   selected9   selected10);
        DialogResult result = MessageBox.Show(this, "Are you sure?", "Upload all", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
       
        if (result == DialogResult.Yes)
        {
          
            List<int> selectedBooleansIndexes = new List<int>();
            int i = 10;
            foreach (bool selected in selectedBools)
            {
                
                i--;
                Console.WriteLine(selected);

                Console.WriteLine(selectedBools[i]);
                if (selected == true)
                {
                    int index = selectedBools.FindIndex(a => a = true);
                    selectedBooleansIndexes.Add(index);
                    Console.WriteLine(selectedBooleansIndexes.Count);
                  }
                if (i == 0)
                {
                    Console.WriteLine(selected1.ToString()   selected2   selected3   selected4   selected5   selected6   selected7   selected8   selected9   selected10);
                    MessageBox.Show(this, selectedBooleansIndexes.Count.ToString(), "siur");
                }


                 
 

Когда я выбираю некоторые изображения, их значение select bool изменяется на true. Поэтому я хотел захватить те, для которых установлено значение true, и получить их индексы, чтобы позже я мог использовать эти индексы при копировании файлов. Проблема в том, что когда я запускаю, если (выбрано == true ) все они кажутся ложными, и ничего не происходит. Я проверил это, вручную введя в состояние консоли каждого bool, и когда я это делаю, все работает так, как задумано. Поэтому моя проблема в том, что когда я использую цикл foreach, каждый статус bool является ложным, даже если это не так ( я проверял это много раз, потому что думал, что что-то переопределяет их в другом месте кода). Может быть, я что-то упускаю, но это странно.

Комментарии:

1. Предположим,… значения в List<bool> не изменятся, если вы измените переменные. В этом разница между типами значений и ссылками. Похоже, вы обновляете selected2 ... только свои переменные, но затем повторяете список, который никогда не обновлялся. Я бы предложил использовать отладчик вместо консоли.журнал «отладка». Это даст вам гораздо лучшее понимание того, что происходит.

2. Создайте объект класса, в котором хранится ссылка на поле изображения, путь / Uri отображаемого изображения, его выбранный статус, пользовательские цвета, которые необходимо задать при выборе / отмене выбора изображения. Позвольте классу подписаться на событие щелчка ваших ящиков с картинками. Добавьте новый экземпляр этого класса в a List<class> для каждого загружаемого изображения. — В конце концов, выберите объекты в списке Where() Selected , в котором находится свойство true . Все необходимые сведения хранятся в объектах класса.

Ответ №1:

Давайте упростим ваш код, чтобы объяснить:

 bool b1 = false;
bool b2 = false
 

До сих пор все шло так, как вы и ожидали. b1 и b2-это и то, и другое false .

 List<bool> l = new List<bool>(){b1, b2};
 

Теперь у вас есть список с копиями b1 и. b2 Это связано с тем, что логические значения являются типами значений.

Что это значит? Если вы изменитесь b1 , [0] то не будете меняться вместе с ним. Если вы изменитесь l[0] , b1 то не будете меняться вместе с ним. То же b2 самое для l[1] и. Они абсолютно независимы.

Давайте теперь перейдем к более серьезной проблеме. Вам определенно не нужны копии, поэтому не создавайте их.

Вместо

 public bool selected1 = false;
[...]
public bool selected10 = false;
 

используйте только список и получайте доступ к записям через их индекс. Подумайте о приложении, которое содержит 1000 изображений вместо 10. Вы бы не хотели объявлять 1000 переменных, не так ли?

Давайте создадим список из 10 логических значений, инициализированных false (потому что это их значение по умолчанию):

 List<bool> selected = new List<bool>(new bool[10]);
 

Давайте также поместим все ваши коробки с картинками в список:

 List<PictureBox> pictures = List<PictureBox>{pctBox1, ... pctBox10};
 

Всякий pctBox1 раз, когда что-то меняется, pictures[0] будет меняться вместе с этим. Это не копия. Это сработает, потому что PictureBox-это ссылочный тип, а не тип значения.

Таким образом, вы можете определить один метод, который выполняет все действия:

 private void DoSomething(int index)
{
        if (selected[index] == false)
        {    
            pictures[index].Image = null;        
            selected[index] = true;
            pictures[index].BackColor = Color.Red;
        }
        else  // DONE: if (selected[index] == true) is unnecessary, because true is the only option left
        {
            selected[index] = false;
            pictures[index].BackColor = Color.White;
            try
            {
                pictures[index].Image = Image.FromFile(filePaths[index   Page * 10]); // refresh image
            }
            catch { } // TODO: fix bad error handling
        }
 }
 

и каждый обработчик событий щелчка становится таким же простым, как

 private void pictureBox2_Click_1(object sender, EventArgs e)
{
    DoSomething(0);  // change index only
}
 

Как правило, мы бы еще больше упростили этот DoSomething() метод.

 private void DoSomething(int index)
{   
    selected[index] = !selected[index];  // Flip the value
    pictures[index].BackColor = selected[index]?Color.White:Color.Red;  // Choose the back color
    pictures[index].Image = null;  // Reset always, since it doesn't really matter
    if (selected[index])
    {
        try
        {
            pictures[index].Image = Image.FromFile(filePaths[index   Page * 10]); // refresh image
        }
        catch {} // TODO: still fix bad error handling
    }
}
 

Я думаю, на сегодня этого достаточно. Вероятно, также не нужно было бы создавать 10 графических полей вручную, но их нужно создавать в цикле.

Комментарии:

1. Спасибо! Сработало очень хорошо, спасибо, что все объяснил, чувак