#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. Спасибо! Сработало очень хорошо, спасибо, что все объяснил, чувак