CellEditor value rollback in objectlistview - c#

I use objectlistview (2.9.1), I want to rollback the value of CellEditor.Text when the input is not qualified, and display on UI immediately.
Code:
private void olv_CellEditFinishing(object sender, CellEditEventArgs e)
{
int iQuantity = 0;
int iPreviousQuantity = order.Quantity.HasValue ? order.Quantity.Value : 0;
string sCellText = ((ObjectListView)sender).CellEditor.Text;
if (Int32.TryParse(sCellText, out iQuantity) && iQuantity >100)
{
// pop up a message box
//Here I want to rollback the previouse quantity
((ObjectListView) sender).CellEditor.Text = iPreviousQuantity.ToString();
//display the previous quantity immedidatly
this.olv.RefreshItem(e.ListViewItem);
}
}
but this does not work.

Make sure you register the event :
this.DBTLviewAfter.CellEditFinishing += new BrightIdeasSoftware.CellEditEventHandler(this.DBTLviewAfter_CellEditFinishing);
and here is my event function:
private void DBTLviewAfter_CellEditFinishing(object sender, CellEditEventArgs e)
{
string toBeEditingStr = (string)e.NewValue;
if(toBeEditingStr == "")
{
e.Cancel = true;
}
}
If the value after edited is empty, the cell won't be changed.

Related

DataGridView Not Updating in C# When Binding Source is Correct

I have a DataGridView and an Edit button. When I click the Edit button and change a field, I press Save and the DataGridView comes up again. The problem is that my changes aren't showing.
Using the debugger, I have looked in the DGV and in the BindingSource and the correct data is there. It is just not displaying in the DGV.
Here is my code - I do realize that it is semi-redundant but, at this point, I'm four hours into it and am willing to try anything.
this.iSOXTableAdapter.FillByISOX(this.MSDataSet.ISOX);
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = iSOXBindingSource;
iSOXDataGridView.DataSource = null;
iSOXDataGridView.DataSource = bindingSource;
bindingSource.ResetBindings(false);
this.iSOXDataGridView.Refresh();
I have looked at the following questions (and many others) and tried their suggestions to no avail:
Datagridview not updating correctly
dataGridView not updating c#?
DataGridView not updating in c#
Best way to refresh DataGridView when you update the base data source
How to refresh or show immediately in datagridview after inserting?
I appreciate any help or suggestions or ideas for workarounds. Thank you so much for looking at this.
***************** EDIT *******************
Here is the code for the save button - I know it is working because after I requery the data, it is in the binding source and in the DGV. This code is in a separate add/edit form:
private void BtnSave_Click(object sender, EventArgs e)
{
if (ValidateForm())
{
ISOXBindingNavigatorSaveItem_Click(sender, e);
this.Close();
}
else
{
MessageBox.Show("Not Validated - Could not Save");
}
}
Here is full code for the user control with the DGV on it:
public partial class FindISOXControl : UserControl
{
private bool gridInitialized = false;
public delegate void ItemHasBeenSelected(object sender, SelectedItemEventArgs e);
public event ItemHasBeenSelected SelectedItem;
public class SelectedItemEventArgs : EventArgs
{
public int SelectedChoice { get; set; }
}
public bool First = true;
public FindISOXControl()
{
InitializeComponent();
FillTableAdapter();
iSOXDataGridView.Columns.Cast<DataGridViewColumn>().ToList().ForEach(f => f.SortMode = DataGridViewColumnSortMode.NotSortable);
}
public void FillTableAdapter()
{
this.iSOXTableAdapter.FillByISOX(this.MSDataSet.ISO);
BindingSource bindingSource = new BindingSource();
bindingSource.DataSource = iSOXBindingSource;
iSOXDataGridView.DataSource = null;
iSOXDataGridView.DataSource = bindingSource;
bindingSource.ResetBindings(false);
this.iSOXDataGridView.Refresh();
setGridData();
}
public void UpdateISOXText(string pISOX = "")
{
this.txtFind.Text = pISOX;
txtFind.Refresh();
}
DataTable dt = new DataTable();
public void btnFind_Click(object sender, EventArgs e)
{
{
setGridData();
}
}
public void setGridData()
{
GetData();
if (iSOXDataGridView.RowCount > 0)
{
EventArgs e = new EventArgs();
iSOXDataGridView_SelectionChanged(null, e);
}
}
public void txtISOX_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Tab)
{
setGridData();
}
}
//Query database
public void GetData()
{
String searchValue = txtFind.Text.Trim().ToUpper();
int rowIndex = -1;
foreach (DataGridViewRow row in iSOXDataGridView.Rows)
{
if (row.Cells[0].Value.ToString().Contains(searchValue))
{
rowIndex = row.Index;
break;
}
}
if (rowIndex == -1)
{
foreach (DataGridViewRow row in iSOXDataGridView.Rows)
{
if (row.Cells[4].Value.ToString().ToUpper().Contains(searchValue))
{
rowIndex = row.Index;
break;
}
}
}
if (rowIndex == -1)
{
if (searchValue != null && searchValue !="")
{
MessageBox.Show(searchValue + " Not Found");
}
}
else
{
iSOXDataGridView.Rows[rowIndex].Selected = true;
iSOXDataGridView.CurrentCell = iSOXDataGridView.Rows[rowIndex].Cells[0];
}
}
public void iSOXDataGridView_SelectionChanged(object sender, EventArgs e)
{
if (iSOXDataGridView.CurrentRow != null)
{
int Row = iSOXDataGridView.CurrentRow.Index;
if (gridInitialized)
{
txtFind.Text = iSOXDataGridView[0, Row].Value.ToString();
// 6 is the ID column
DataGridViewCellEventArgs ev = new DataGridViewCellEventArgs(6, Row);
iSOXDataGridView_CellDoubleClick(sender, ev);
}
}
}
private void iSOXDataGridView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.RowIndex < iSOXDataGridView.RowCount)
{
// 6 == id column
int choice = (int)iSOXDataGridView[6, First ? 0 : e.RowIndex].Value;
this.SelectedItem(this, new SelectedItemEventArgs { SelectedChoice = choice });
}
}
private void iSOXDataGridView_RowEnter(object sender, DataGridViewCellEventArgs e)
{
// 6 is the ID column
DataGridViewCellEventArgs ev = new DataGridViewCellEventArgs(6, e.RowIndex);
if (e.RowIndex != 0)
{
First = false;
iSOXDataGridView_CellDoubleClick(sender, ev);
}
}
private void iSOXDataGridView_RowLeave(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex == 0 && e.ColumnIndex == 0)
{ First = true; }
}
}
Here is the code from the main form with the user control on it after it returns from the edit:
uc.FillTableAdapter();
********* EDIT --> Code that is opening Edit form:
AddEditISOX aeix = new AddEditISOX("E", currentISOX);
aeix.ShowDialog();
ISOX_Load(sender, e);
ISOX_Load() calls uc.FillTableAdapter();
A DataGridView sets up bindings the first time you assign the DataSource. The problem is that subsequent DataSource assignments, if the assignments have a different structure from the initial assignment, will fail because the bindings are now "off"
You need to reset the DataGridView thusly so that the data is bound a new. (The link is for VB but you just need to know the methods to call. Even copy/paste would be overkill.)
Maybe you don't have proper update sql commands in the adapter
add these commands to your intialize method
iSOXTableAdapter.Adapter.MissingSchemaAction = MissingSchemaAction.Error;
iSOXTableAdapter.Adapter.MissingMappingAction = MissingMappingAction.Error;
maybe the generated error will tell you what are you missing there
bind your data to the View of table and it would automatically get updates.
I finally figured this blasted thing out. In my Edit Button Click method, I need to call the user control fill table adapter method again.
private void BtnEdit_Click(object sender, EventArgs e)
{
if (currentISOX != 0)
{
AddEditISO aei = new AddEditISOX("E", currentISOX);
aei.ShowDialog();
findISOXControl1.FillTableAdapter();
}
else
{
MessageBox.Show("Please Make a Selection First");
}
}
Thanks for everyone's thoughts, advice and input. It was very helpful and eventually led me to the solution.

How to color different words with different colors in a RichTextBox while a user is writing and raise an event when that colored text is clicked

When a user writes some words in a rich text box, if that word matches some specific word, than the color of the that word should automatically change.
When the user clicks on that particular colored text, it should raise an event.
Given the requirements:
1) A User inserts some text in a RichTextBox Control.
2) If the word entered is part of a pre-defined list of words, that word should change color (so, define a relation between a word and a color).
3) When a mouse Click event is generated on a colored word, an event is raised, to notify which word was clicked.
Possible result (to replicate what's in the visual example):
Define a custom EventHandler with custom EventArgs:
public class WordsEventArgs : EventArgs
{
private string m_word;
public WordsEventArgs(string word) { m_word = word; }
public string Word { get { return m_word; } set { m_word = value; } }
}
public delegate void WordsEventHandler(object sender, WordsEventArgs e);
public event WordsEventHandler WordClicked;
protected void OnWordClicked(WordsEventArgs e) => WordClicked?.Invoke(this, e);
Subscribe to the event:
this.WordClicked += new WordsEventHandler(this.Word_Click);
Simple Class for the list of words:
public class ColoredWord
{
public string Word { get; set; }
public Color WordColor { get; set; }
}
public List<ColoredWord> ColoredWords = new List<ColoredWord>();
Fill the list with some words an related color, then bind it to a ListBox, calling the FillColoredWords() method (in other words, handle a collection of objects that relate pieces of text with Color values):
public void FillColoredWords()
{
ColoredWords.Add(new ColoredWord { Word = "SIMPLE", WordColor = Color.Goldenrod });
ColoredWords.Add(new ColoredWord { Word = "COLORED", WordColor = Color.Salmon });
ColoredWords.Add(new ColoredWord { Word = "TEXT", WordColor = Color.DarkCyan });
this.listBox1.DisplayMember = "Word";
this.listBox1.DataSource = ColoredWords;
}
In the KeyPress event, evaluate whether the last entered word is part of the list of words to color:
private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
{
int currentPosition = richTextBox1.SelectionStart;
if (e.KeyChar == (char)Keys.Space && currentPosition > 0 && richTextBox1.Text.Length > 1) {
int lastSpacePos = richTextBox1.Text.LastIndexOf((char)Keys.Space, currentPosition - 1);
lastSpacePos = lastSpacePos > -1 ? lastSpacePos + 1 : 0;
string lastWord = richTextBox1.Text.Substring(lastSpacePos, currentPosition - (lastSpacePos));
ColoredWord result = ColoredWords.FirstOrDefault(s => s.Word == lastWord.ToUpper());
richTextBox1.Select(lastSpacePos, currentPosition - lastSpacePos);
if (result != null) {
if (richTextBox1.SelectionColor != result.WordColor) {
richTextBox1.SelectionColor = result.WordColor;
}
}
else {
if (richTextBox1.SelectionColor != richTextBox1.ForeColor) {
richTextBox1.SelectionColor = richTextBox1.ForeColor;
}
}
richTextBox1.SelectionStart = currentPosition;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionColor = richTextBox1.ForeColor;
}
}
In the MouseClick event, verify whether the event is generated on a colored word.
In that case, raise the custom OnWordClicked() event:
private void richTextBox1_MouseClick(object sender, MouseEventArgs e)
{
if (richTextBox1.SelectionColor.ToArgb() != richTextBox1.ForeColor.ToArgb()) {
try {
int wordInit = richTextBox1.Text.LastIndexOf((char)32, richTextBox1.SelectionStart);
wordInit = wordInit > -1 ? wordInit : 0;
int wordEnd = richTextBox1.Text.IndexOf((char)32, richTextBox1.SelectionStart);
string wordClicked = richTextBox1.Text.Substring(wordInit, wordEnd - wordInit) + Environment.NewLine;
OnWordClicked(new WordsEventArgs(wordClicked));
}
catch (Exception) {
//Handle a fast DoubleClick: RTB is a bit dumb.
//Handle a word auto-selection that changes the `.SelectionStart` value
}
}
}
In the custom event, you can append the clicked word to a TextBox (or do whatever else you want to do with it):
private void Word_Click(object sender, WordsEventArgs e)
{
textBox1.AppendText(e.Word);
}
first of all add an event to your rich box text changed,then
you need to change the color of text if that is an specific word like for example : Munis , Ali
private void Rchtxt_TextChanged(object sender, EventArgs e)
{
this.CheckKeyword("Munis", Color.Purple, 0);
this.CheckKeyword("Ali", Color.Green, 0);
}

How to disable button by selecting comboBox value

I have a comoboBox that is binded to sql database, and I added a default text at index 0 like this
string s = "< -------------Select an application ----------->";
applicationComboBox.Items.Insert(0, s);
applicationComboBox.SelectedIndex = 0;
I am wondering if there is a way to disable my button if the the string s at index 0 is select? In my comboBox, I binded the data with the while(SQLReader.Read()) method instead of using ValueMember and `DisplayMember
Here is what I tried but no luck
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
for (int i = 1; i < applicationComboBox.Items.Count; i++)
{
string value = applicationComboBox.GetItemText(applicationComboBox.Items[0]);
string s = "<------------- Select an application ----------->";
if (value == s)
{
exportButton.Enabled = false;
MessageBox.Show(value); //nothing happen
this.teacherCheckListBox.DataSource = null;
teacherCheckListBox.Items.Clear();
}
else
{
exportButton.Enabled = true;
}
}
}
}
Use SelectedIndex property to know which item is selected and disable the button if it is first item.
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
{
exportButton.Enabled = false;
}
}

DevExpress & C# : Validate RepositoryItemLookUpEdit cell after choosing value

I have a GridView in which i have this column :
bandedGridColumn.ColumnEdit = InitEdit_Material();
Here is the InitEdit_Material method :
public static RepositoryItemLookUpEdit InitEdit_Material()
{
RepositoryItemLookUpEdit riMaterial = new RepositoryItemLookUpEdit();
riMaterial.Columns.Add(new LookUpColumnInfo("ID", "ID"));
riMaterial.Columns.Add(new LookUpColumnInfo("CustomsMaterial.Name", "Name"));
riMaterial.DataSource = Service.GetAll(svc.EntityTypeToGet.Material).Data.All_Material;
riMaterial.DisplayMember = "MaterialFullname";
riMaterial.ValueMember = "ID";
riMaterial.AutoSearchColumnIndex = 1;
riMaterial.BestFitMode = BestFitMode.BestFitResizePopup;
riMaterial.NullText = "";
return riMaterial;
}
This is what it looks like :
I want to perform some actions (set other cell's value based on current cell value) whenever user choose a new value in this cell, but the problem is all the possible event i know only fires once the cell lost focus, i've tried :
private void vwVD_ValidatingEditor(object sender, BaseContainerValidateEditorEventArgs e)
{
if (vwVD.FocusedColumn.Name == "colMaterialID")
MessageBox.Show("only show when focus lost");
return;
}
private void vwVD_CellValueChanged(object sender, CellValueChangedEventArgs e)
{
if (e.Column.Name != "colMaterialID") return;
MessageBox.Show("only show when focus lost");
}
You can try to use GridView.CellValueChanging event:
private void vwVD_CellValueChanging(object sender, CellValueChangedEventArgs e)
{
if (vwVD.FocusedColumn.Name == "colMaterialID")
{
//Perform some actions. Use e.Value.
}
}

BackgroundWorker for implementing "Search as you type" Combobox

I have created a code for my combobox, that can search addresses in a very large table on Sql Server with the help of stored procedure (i'm working with Entity framework). My stored procedure returns 10 hits and my code fills the combobox with search results. For doing this I'm using BackgroundWorker.
But here I'm now having big problems:
- although the combobox is filled with my search results, it always has the first item selected. Even if I type in only a letter, the whole text gets selected;
After that searching for the address doesn't work anymore. It searches only among these 10 results and I'm having no idea how to solve this. Here is my whole code, that causes me problems:
public String searchedItem = "";
public delegate void DelegateUpdateComboboxSelection(ComboBox myCombo,string value,int count);
BackgroundWorker m_bgworker = new BackgroundWorker();
static AutoResetEvent resetWorker = new AutoResetEvent(false);
m_bgworker.WorkerSupportsCancellation = true;
m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
BindingList<spIskalnikNaslovi_Result1> m_addresses = new BindingList<SP_Result1>();
void m_bgworker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
int count = (int)((object[])e.Result)[0];
string value = (string)((object[])e.Result)[1];
ComboBox myCombo = (ComboBox)((object[])e.Result)[2];
DelegateUpdateComboboxSelection ndelegate = new DelegateUpdateComboboxSelection(UpdateComboSelection);
if (this.InvokeRequired)
{
Invoke(ndelegate, new object[] {myCombo, value, count});
return;
}
else
{
UpdateComboSelection(myCombo, value, count);
return;
}
}
private void UpdateComboSelection(ComboBox myCombo, String value, int count)
{
myCombo = comboBox9;
myCombo.DataSource = m_addresses;
searchedItem = myCombo.Text;
if (count > 0)
{
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
}
}
public void FillComboboxBindingList(object sender, DoWorkEventArgs e)
{
if (m_bgworker.CancellationPending)
{
resetWorker.Set();
e.Cancel = true;
return;
}
else
{
string value = (String)((Object[])e.Argument)[0];
List<SP_Result1> result;
result = _vsebina.SP_searcher(value).ToList<SP_Result1>();
m_addresses = new BindingList<SP_Result1>();
foreach (SP_Result1 rez in result)
{
if (m_addresses.Contains(rez))
{
continue;
}
else
{
m_addresses.Add(rez);
}
}
foreach (SP_Result1 r in m_addresses.ToArray())
{
if (!result.Contains(r))
{
m_addresses.Remove(r);
}
}
e.Result = new object[] { rezultat.Count, vrednost, null };
return;
}
}
private void comboBox9_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int searchStart = comboBox9.SelectionStart;
if (searchStart > 0)
{
searchStart--;
if (searchStart == 0)
{
comboBox9.Text = "";
}
else
{
comboBox9.Text = comboBox9.Text.Substring(0, searchStart + 1);
}
}
else
{
searchStart = 0;
}
e.Handled = true;
}
}
private void comboBox9_Enter(object sender, EventArgs e)
{
comboBox9.SelectionStart = 0;
comboBox9.SelectionLength = 0;
}
private void comboBox9_Click(object sender, EventArgs e)
{
comboBox9.Text = "";
}
private void comboBox9_KeyPress(object sender, KeyPressEventArgs e)
{
Search();
}
public void Search()
{
if (comboBox9.Text.Length < 4)
{
return;
}
else
{
if (m_bgworker.IsBusy)
{
m_bgworker.CancelAsync();
m_bgworker = new BackgroundWorker();
m_bgworker.WorkerSupportsCancellation = true;
m_bgworker.DoWork += new DoWorkEventHandler(FillComboboxBindingList);
m_bgworker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_bgworker_RunWorkerCompleted);
}
m_bgworker.RunWorkerAsync(new object[] { comboBox9.Text, comboBox9 });
}
}
Maybe can someone enlighten me, what I'm doing wrong. This is first time, that I'm using BackgroundWorker. I have no idea, how
to achieve "search as you type" with combobox in any other way, because my datatable with addresses is quite large (million records).
Thanks in advance for any kind of help or code example.
Vladimir
Edit 1:
Ok, here is my code, before I have used BackGroundWorker. It worked, but it searches very very slow (it can take up to 10 seconds):
private void comboBox9_TextChanged(object sender, EventArgs e)
{
if (comboBox9.Text.Length < 4)
{
return;
}
else
{
FillCombobox(comboBox9.Text, comboBox9);
}
}
public void FillCombobox(string value, ComboBox myCombo)
{
List<spIskalnikNaslovi_Result1> result;
result = _vsebina.spIskalnikNaslovi1(value).ToList();
if (result.Count() > 0)
{
myCombo.DataSource = result;
myCombo.ValueMember = "HS_MID";
myCombo.DisplayMember = "NASLOV1";
var searchedItem = myCombo.Items[0].ToString();
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
}
return;
}
Is there a way to speed this up without having backgroundworker?
make a button you will call searchbutton
and in click_event of this button call your search() method that run your backgroundworker
that fill the combobox
clear you key_press event of your combobox and it will work
the mistake is you key_press event that call every key stroke happening your search method
so retrieve it
You should get your items in a list, use that list to populate your combobox.
then set AutoCompleteMode property value to Suggest or Append or SuggestAppend and set AutoCompleteSoucre property value to ListItems.
For "Search as you Type", which is actually "Filter as you Type" more than search, you need to implement the OnKeyDown or KeyPressed event.
What you would do is take the search string, which is the current text at the time of the event, then filter the master list using that string. Normally one would use "Starts With" for the filtering, but you could also simply use "Contains". Then you live update the contents of the box with the results from the filter. This is accomplished by changing and refreshing the Datasource.
Here is my final solution without BackGroundWorker. It works quick with my large table, and is upgraded for using a stored procedure on SQL Server (if you use Entity Framework). I use Timer to make sure the user can find a value, that he is searching.
Here you can see the original solution, that I found on this site (thanks to Max Lambertini and algreat for the idea and working concept):
C# winforms combobox dynamic autocomplete
My solution:
private bool _canUpdate = true;
private bool _needUpdate = false;
List<spIskalnikNaslovi_Result1> dataFound;
private void comboBox12_TextChanged(object sender, EventArgs e)
{
if (_needUpdate)
{
if (_canUpdate)
{
_canUpdate = false;
refreshData();
}
else
{
restartTimer();
}
}
}
private void comboBox12_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
int searchStart = comboBox12.SelectionStart;
if (searchStart > 0)
{
searchStart--;
if (searchStart == 0)
{
comboBox12.Text = "";
}
else
{
comboBox12.Text = comboBox12.Text.Substring(0, searchStart + 1);
}
}
else
{
searchStart = 0;
}
e.Handled = true;
}
}
private void comboBox12_TextUpdate(object sender, EventArgs e)
{
_needUpdate = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
_canUpdate = true;
timer1.Stop();
refreshData();
}
private void refreshData()
{
if (comboBox12.Text.Length > 1)
{
FillCombobox(comboBox12.Text, comboBox12);
}
}
private void restartTimer()
{
timer1.Stop();
_canUpdate = false;
timer1.Start();
}
private void FillCombobox(string value, ComboBox myCombo)
{
dataFound = _vsebina.spIskalnikNaslovi1(value).ToList();
if (dataFound.Count() > 0)
{
myCombo.DataSource = dataFound;
myCombo.ValueMember = "HS_MID";
myCombo.DisplayMember = "NASLOV1";
var searchedItem = myCombo.Items[0].ToString();
myCombo.SelectionStart = value.Length;
myCombo.SelectionLength = searchedItem.Length - value.Length;
myCombo.DroppedDown = true;
return;
}
else
{
myCombo.DroppedDown = false;
myCombo.SelectionStart = value.Length;
return;
}
}

Categories