I have a question to get all deleted items to a new list and also for the changed items. I'm using a datagridview with a sortable bindingsource. For all new items it's already working(last part of the code)
Thanks!
namespace Levelapp
{
public partial class LevelView : Form
{
FilterLevel m_filterLevel;
int m_filterLevelTotal;
public LevelView()
{
InitializeComponent();
}
public LevelView(FilterLevel opt)
{
InitializeComponent();
m_filterLevel = opt;
bindingSource1.DataSource = typeof(LevelResource);
dataGridView1.DataSource = bindingSource1;
bindingSource1.DataSource = m_filterLevel.FoundLevels;
m_filterLevelTotal = bindingSource1.Count;
}
private void newSheet_Click(object sender, EventArgs e)
{
string newItemName = "Sheet" + " " + "1";
string newItemNumber = "A-00";
LevelResource newItem = new LevelResource();
newItem.Name = newItemName;
newItem.Number = newItemNumber;
bindingSource1.Add(newItem);
}
private void deleteSheet_Click(object sender, EventArgs e)
{
bindingSource1.RemoveCurrent();
}
private void ok_Click(object sender, EventArgs e)
{
for (int i = m_filterLevelTotal; i < bindingSource1.Count; i++)
{
bindingSource1.Position = i;
LevelResource newSheet = bindingSource1.Current as LevelResource;
}
}
}
}
Thanks for the quick response. But i get an Error at the bool result line. This code will be used in Revit. Below the part how i put your code under the deleteSheet button
private void deleteSheet_Click(object sender, EventArgs e)
{
for (int i = 0; i < bindingSource1.Count; i++)
{
bindingSource1.Position = i;
var view = bindingSource1.Current as DataRowView;
bool result = view.Row.RowState == DataRowState.Added || view.Row.RowState == DataRowState.Unchanged;
if (result)
{
// new or didn't modified, work as normal
}
else
{
// add to another list
}
}
}
Related
I'm trying to select all checkboxes, but It have an error.
If I click the full check/release checkbox at the top while a column containing a checkbox is selected, the selected area doesn't change.
How should I solve it?
The picture above is after clicking the full release.
This is my test code.
The function dataGridView1_CellPainting() and dgvCheckBox_CheckedChanged() are used for full check/release operation.
namespace TestWinForm
{
public partial class Form1 : Form
{
List<string> saved_file_names = new List<string>();
int table_index = 0;
public Form1()
{
InitializeComponent();
}
private void add_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "열기";
ofd.Filter = "txt파일 | *.txt";
ofd.Multiselect = true; // 파일 다중 선택
DialogResult dr = ofd.ShowDialog();
if (dr == DialogResult.OK)
{
foreach (string file_name in ofd.FileNames)
{
// 1. 중복체크
if (saved_file_names.Contains(file_name))
continue;
// 2. 중복되지않은 파일들을 추가.
dataGridView1.Rows.Add();
dataGridView1.Rows[table_index].Cells[1].Value = table_index + 1;
dataGridView1.Rows[table_index].Cells[2].Value = file_name;
saved_file_names.Add(file_name);
dataGridView1.Rows[table_index].Cells[3].Value = "none";
table_index++;
}
}
}
private void delete_Click(object sender, EventArgs e)
{
bool is_checked = false;
List<int> delete_index = new List<int>();
for (int i = 0; i < table_index; i++)
{
if (Convert.ToBoolean(dataGridView1.Rows[i].Cells[0].Value) == true)
delete_index.Add(i);
}
if (delete_index.Count == 0)
return;
delete_index.Reverse();
foreach (var index in delete_index)
{
table_index--;
saved_file_names.RemoveAt(index);
dataGridView1.Rows.RemoveAt(index);
}
}
private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e)
{
if (e.ColumnIndex == 0 && e.RowIndex == -1)
{
e.PaintBackground(e.ClipBounds, false);
Point pt = e.CellBounds.Location;
int nChkBoxWidth = 15;
int nChkBoxHeight = 15;
int offsetx = (e.CellBounds.Width - nChkBoxWidth) / 2;
int offsety = (e.CellBounds.Height - nChkBoxHeight) / 2;
pt.X += offsetx;
pt.Y += offsety;
CheckBox cb = new CheckBox();
cb.Size = new Size(nChkBoxWidth, nChkBoxHeight);
cb.Location = pt;
cb.Checked = true;
cb.CheckedChanged += new EventHandler(dgvCheckBox_CheckedChanged);
((DataGridView)sender).Controls.Add(cb);
e.Handled = true;
}
}
private void dgvCheckBox_CheckedChanged(object sender, EventArgs e)
{
foreach (DataGridViewRow r in dataGridView1.Rows)
{
r.Cells[0].Value = ((CheckBox)sender).Checked;
}
}
}
}
Please consider using Data Binding with your DataGridView which can simplify what you're trying to do. By defining a Record class with your bool IsChecked property, the checkbox row is created automatically when you add that record to a binding list of those records. Then you can manipulate that check by setting the property in your record instead of making calls on the UI object itself.
Clicking the header cell :
If All are either checked or unchecked then all will toggle.
If there is a mix of checked and unchecked, then all will be promoted to checked.
Here's a working sample on GitHub.
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Forms;
namespace dgv_ac
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>
/// Wait for the main form to be created, then attach
/// your Binding List as the data source of the DGV
/// </summary>
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
dataGridView1.DataSource = this.DataSource;
initDGV();
}
private void initDGV()
{
dataGridView1.AllowUserToAddRows = false;
// Now you can populate the DataGridView simply
// by adding some records to the list.
for (int i = 0; i < 5; i++)
{
DataSource.Add(new Record { Number = i, FileName = $"MyFile_{i}.txt" });
}
// Once the first record is added, the Columns information is
// available and we can do column formatting.
dataGridView1.Columns[nameof(Record.FileName)].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
var checkboxColumn = dataGridView1.Columns[nameof(Record.IsChecked)];
checkboxColumn.HeaderText = string.Empty;
checkboxColumn.Width = 40;
dataGridView1.CellClick += onCellClick;
dataGridView1.CellContentClick += onCellContentClick;
}
/// <summary>
/// Detect check box click and end the edit mode in this case.
/// </summary>
private void onCellContentClick(object sender, DataGridViewCellEventArgs e)
{
if(e.RowIndex != -1)
{
var cell = dataGridView1[e.ColumnIndex, e.RowIndex];
if(cell is DataGridViewCheckBoxCell checkbox)
{
dataGridView1.EndEdit();
}
}
}
/// <summary>
/// Detect header click and set the records accordingly.
/// </summary>
private void onCellClick(object sender, DataGridViewCellEventArgs e)
{
if(e.RowIndex == -1)
{
switch (dataGridView1.Columns[e.ColumnIndex].Name)
{
case nameof(Record.IsChecked):
if (DataSource.Any()) // Check to see if there are any records at all.
{
if(DataSource.Count(record=>record.IsChecked) == DataSource.Count)
{
// This block says thet're all chacked or all unchecked.
if(DataSource.First().IsChecked) // then they all are
{
setAll(false);
}
else
{
setAll(true);
}
}
else setAll(true); // If they're mixed, make them all checked.
}
break;
}
}
void setAll(bool value)
{
foreach (var record in DataSource)
{
record.IsChecked = value;
}
Refresh();
}
}
public BindingList<Record> DataSource = new BindingList<Record>();
}
// This is the record class that will provide column
// information to the DataGridView automatically.
public class Record
{
public int Number { get; set; }
public bool IsChecked { get; set; }
public string FileName { get; set; }
}
}
I have an object list view that has two text columns. When I edit the left column and hit tab to go to the right I receive a "ArgumentOutOfRangeException" with an index of -1. Looks like the index is something internal to the list view because I debugged my application and found no errors. Here is the code :
public partial class SummaryOverviewSettingsDlg : Form
{
private List<SummaryDataset> _localSummaryDatasets = new List<SummaryDataset>();
private bool _includeLimits;
private SummaryOverviewSettings _summaryOverviewSettings;
public bool IncludeLimits { get { return _includeLimits; } }
public SummaryOverviewSettingsDlg(SummaryOverviewSettings summaryOverviewSettings)
{
InitializeComponent();
if (summaryOverviewSettings.Datasets != null)
{
_localSummaryDatasets.AddRange(summaryOverviewSettings.Datasets);
}
_summaryOverviewSettings = summaryOverviewSettings;
}
private void DataFilesListDlg_Load(object sender, EventArgs e)
{
foreach(var dataFile in _localSummaryDatasets)
{
olvFilePaths.AddObject(dataFile);
}
LimitsCheckbox.Checked = _summaryOverviewSettings.ShowLimits;
}
private void OlvFilePaths_CellRightClick(object sender, CellRightClickEventArgs e)
{
var contextMenuSymbol = new ContextMenuStrip();
ToolStripItem item;
item = contextMenuSymbol.Items.Add("Add sample");
item.Click += ContextMenuAddFilePath;
if (e.Model != null)
{
contextMenuSymbol.Items.Add("-");
item = contextMenuSymbol.Items.Add("Delete sample");
item.Click += ContextMenuDeleteFilePath;
}
olvFilePaths.ContextMenuStrip = contextMenuSymbol;
}
private void ContextMenuAddFilePath(object sender, EventArgs e)
{
var item = new SummaryDataset()
{
SampleName = "Sample",
Path = "Path"
};
_localSummaryDatasets.Add(item);
// Rebuild the list in the GUI
olvFilePaths.ClearObjects();
foreach (var dataFile in _localSummaryDatasets)
{
olvFilePaths.AddObject(dataFile);
}
olvFilePaths.AutoResizeColumns();
}
private void ContextMenuDeleteFilePath(object sender, EventArgs e)
{
if (olvFilePaths.SelectedObject != null)
{
var item = (SummaryDataset)olvFilePaths.SelectedObject;
olvFilePaths.RemoveObject(item);
_localSummaryDatasets.Remove(item);
}
}
private void OlvFilePaths_CellEditFinished(object sender, CellEditEventArgs e)
{
if (e.Control is TextBox textBox)
{
var oldValue = (string)e.Value;
var newValue = (string)e.NewValue;
var col = e.Column.AspectName;
var index = e.ListViewItem.Index;
if (newValue != oldValue)
{
if (col == "SampleName")
{
_localSummaryDatasets[index].SampleName = newValue;
}
else
{
_localSummaryDatasets[index].Path = newValue;
}
}
}
// Rebuild the list in the GUI
olvFilePaths.ClearObjects();
foreach (var dataFile in _localSummaryDatasets)
{
olvFilePaths.AddObject(dataFile);
}
olvFilePaths.AutoResizeColumns();
}
private void OkButton_Click(object sender, EventArgs e)
{
_summaryOverviewSettings.Datasets.Clear();
_summaryOverviewSettings.Datasets.AddRange(_localSummaryDatasets);
_summaryOverviewSettings.ShowLimits = _includeLimits;
DialogResult = DialogResult.OK;
Close();
}
private void ButtonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void LimitsCheckbox_CheckedChanged(object sender, EventArgs e)
{
_includeLimits = LimitsCheckbox.Checked;
}
}
string Path = #"C:\Users\Alexander\Desktop\Adressbok\Adressbok.txt";
List<string> sökhistorik;
//Lista
List<Person> Personer = new List<Person>();
//instans
Person p1 = new Person();
public Form1()
{
InitializeComponent();
}
private void updateUI()
{
lstBox.DataSource = null;
lstBox.DataSource = Personer;
}
private void btnSpara_Click(object sender, EventArgs e)
{
p1.Namn = tbxNamn.Text;
p1.Gatuadress = tbxGatuadress.Text;
p1.Postnummer = tbxPostnummer.Text;
p1.Postort = tbxPostort.Text;
p1.Telefonnummer = tbxTelefonnummer.Text;
p1.Epost = tbxEpost.Text;
Personer.Add(p1);
updateUI();
SaveToFile();
tbxNamn.Text = "";
tbxGatuadress.Text = "";
tbxPostnummer.Text = "";
tbxPostort.Text = "";
tbxTelefonnummer.Text = "";
tbxEpost.Text = "";
}
I want to edit the selected item from listbox and then edit the information and save it again and then make a delete button and delete the whole information. How do i do it. Im using windows forms c#.
Why don''t you use BindingList instead of List?
BindingList will automatically update your UI based on your source.
Assuming Person has a ToString(),
// Bind BindingList to Listbox
public class Form1 {
BindingList<Person> personer = new BindingList<Person>();
public Form1() {
InitializeComponent();
listBox1.DataSource = personer;
}
// Remove on button click
private void button1_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex > -1)
{
//This automatically updates your listBox
personer.RemoveAt(listBox1.SelectedIndex);
}
}
// Update on Button click
private void button2_Click(object sender, EventArgs e)
{
if (listBox1.SelectedIndex > -1)
{
Person p = personer[listBox1.SelectedIndex];
//Update person here
}
}
I want to add text from textbox to string[] array by pressing button3 i value will add to new array and clear textbox.
Button1 is to go up on array and Button2 is for go down.
I make this but it wont work:
namespace Test
{
public partial class Form1 : Form
{
public int arr1 = 0;
public int arr2 = 0;
public string[] array = new string[100];
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (arr1 < array.Length - 1)
{
if (array[arr1] != "")
{
arr1++;
textBox1.Text = array[arr1];
}
}
else
{
arr1 = 0;
}
}
private void button2_Click(object sender, EventArgs e)
{
if (arr1 < array.Length - 1)
{
if (array[arr1] != "")
{
arr1--;
textBox1.Text = array[arr1];
}
}
else
{
arr1 = 0;
}
}
private void button3_Click(object sender, EventArgs e)
{
array[arr1] = textBox1.Text;
listBox1.Items.Add(array[arr1]);
arr2++;
textBox1.Text = "";
}
}
}
Can someone help me with this?
Thanks
replace arr2++ by arr1++ as following
private void button3_Click(object sender, EventArgs e)
{
array[arr1] = textBox1.Text;
listBox1.Items.Add(array[arr1]);
arr1++;
textBox1.Text = "";
}
I'm writing a program to filter meal types into different categories using an observable collection. I'm using enums to categorise the meals, and I have three separate methods with the same code to split them into new collections when their respective buttons are clicked. The three enum types are, Vegetarian, Meat, and Fish. I have two observable collections, meals and filteredMeals. I was trying to create another method then pass down the Category as a parameter but I couldn't get it to work! Any help would be greatly appreciated.
private void btnVegetarian_Click(object sender, RoutedEventArgs e)
{
filteredMeals = new ObservableCollection<Meal>();
Meal newMeal = new Meal();
for (int i = 0; i < meals.Count; i++)
{
newMeal = meals[i];
if (newMeal.Category == MealCategory.Vegetarian)
{
filteredMeals.Add(newMeal);
}
}
lbxMeals.ItemsSource = filteredMeals;
}
private void btnMeat_Click(object sender, RoutedEventArgs e)
{
filteredMeals = new ObservableCollection<Meal>();
Meal newMeal = new Meal();
for (int i = 0; i < meals.Count; i++)
{
newMeal = meals[i];
if (newMeal.Category == MealCategory.Meat)
{
filteredMeals.Add(newMeal);
}
}
lbxMeals.ItemsSource = filteredMeals;
}
private void btnFish_Click(object sender, RoutedEventArgs e)
{
filteredMeals = new ObservableCollection<Meal>();
Meal newMeal = new Meal();
for (int i = 0; i < meals.Count; i++)
{
newMeal = meals[i];
if (newMeal.Category == MealCategory.Fish)
{
filteredMeals.Add(newMeal);
}
}
lbxMeals.ItemsSource = filteredMeals;
}
You need to create a new method taking a MealCategory parameter. Move the code to there, and pass the appropiate MealCategory for each of your button click handlers.
The code could then look like this:
private void btnVegetarian_Click(object sender, RoutedEventArgs e)
{
FilterMeals(MealCategory.Vegatarian);
}
private void btnMeat_Click(object sender, RoutedEventArgs e)
{
FilterMeals(MealCategory.Meat);
}
private void btnFish_Click(object sender, RoutedEventArgs e)
{
FilterMeals(MealCategory.Fish);
}
private void FilterMeals(MealCategory category)
{
filteredMeals = new ObservableCollection<Meal>();
Meal newMeal = new Meal();
for (int i = 0; i < meals.Count; i++)
{
newMeal = meals[i];
if (newMeal.Category == category)
{
filteredMeals.Add(newMeal);
}
}
lbxMeals.ItemsSource = filteredMeals;
}
Once you've got that working, you could try refactoring your FilterMeals method to be shorter. You can use LINQ to express the filter, and the ObservableCollection constructor has an overload taking an IEnumerable<T>, which could simplify it to:
private void FilterMeals(MealCategory category)
{
var filteredMeals = meals.Where(m => m.Category == category);
lbxMeals.ItemsSource = new ObservableCollection<Meal>(filteredMeals);
}
private void btnVegetarian_Click(object sender, RoutedEventArgs e)
{
Filer(MealCategory.Vegatarian).Invoke();
}
private void btnMeat_Click(object sender, RoutedEventArgs e)
{
Filer(MealCategory.Meat).Invoke();
}
private void btnFish_Click(object sender, RoutedEventArgs e)
{
Filer(MealCategory.Fish).Invoke();
}
public Action Filer(MealCategory mealCategory)
{
lbxMeals.ItemsSource = new ObservableCollection<Meal>(meals.Where(m=>m.Category=mealCategory))
}
Too cumbersome. You can simply do this:
private void btnMeat_Click(object sender, RoutedEventArgs e)
{
lbxMeals.ItemsSource = new ObservableCollection<Meal>(
meals.Where(m => m.Category == MealCategory.Meat));
}
and of course the same for Vegetarian and Fish.