I have a text box that is going to be populated with a comma spereated list that is driven by a CheckedListBox control.
The idea is that as the user checks items off in the list, they will appear in the text field above. I have this working to the point where if I check an item and then click somewhere else inside the control then the text ends up in the textbox. I am capturing the click event on my control.
If I use the item_checked event then the list in the text box isn't updated until I check a second item (at which point in time only the first item that was checked is displayed in the text box.) Is there anyway around this? Reading on MSDN doesn't seem to show any other events that would be applicable.
I'm using .net 1.1.
This is the method that is run on the event trap.
Private Sub FillCheckedTagsTextBox()
txtSelectedTags.Text = ""
Dim tagChecked As Object
For Each tagChecked In cltTagSelection.CheckedItems
txtSelectedTags.Text = txtSelectedTags.Text + tagChecked.ToString() + ", "
Next
End Sub
Thanks,
Mike
Ouch 1.1? Is your employer trying to kill you? I'd try to push up to 2.0 if I could.
To double check when you say the "Checked" event do you mean CheckedChanged? In 2.00 this works fine on desktop. Is it a bug in 1.1?
If it is a bug (check your own code first before deciding this! Then check it again!) then I can suggest trying to capture the Leave event which occurs when a control loses focus. Failing this you could databind a business object to the .Checked property and then fire your own event when your value changes. E.G.
public class MyValues
{
private bool _check;
public bool Check
{
get
{
return _check;
}
set
{
if(_check != value)
{
_check = value;
// todo: raise event!
}
}
}
}
Related
I'm developing App which communicate with RFID Reader, I have the following Label which takes it's value from the Reader (when I click on the read button on the hardware)
<Label Text="{Binding Statistics.TotalUniqueCount}" />
I want to handle and event when the text value changed, it looks like the label doesn't has such event, is there any text view control that can handle the text change event? I tried to use Entry control, but the problem that when I read the RFID tags, it gives me the first and second time correct values, but the third time it gives me wrong value , and that's happens only when I use Entry.
for example, I read 3 unique tags, it gives me first time 3, when I read more 2 tags, the number becomes 5, but when I read the third time another 3 tags, the number becomes 1.
I put Entry and Label in the same page with the same Binding, the Label shows correct values and the Entry shows wrong values.
is there any solution to handle event when this binding (Statistics.TotalUniqueCount) changes?
As was mentioned in the comments, it looks like the Statistics class must implement INotifyPropertyChanged (that's how the binding is able to update the UI when the data changes). If that's the case, you should just subscribe to that same event in your code. Wherever you have access to that Statistics variable (in code bebhind or viewmodel), just do
Statistics.PropertyChanged += (o,e)=>
{
if (e.PropertyName == "TotalUniqueCount")
{
//do something
}
}
What you can do is on whatever page/view your label is on create a new bindableproperty that is set to your binding. Then add a propertyChanged method that will get called if the text on your label changes.
public static BindableProperty TextChangedProperty = BindableProperty.Create(nameof(TextChanged), typeof(string), typeof(YourView), string.Empty, propertyChanged:OnTextChanged);
public string TextChanged
{
get { return (string)GetValue(TextChangedProperty); }
set { SetValue(TextChangedProperty, value); }
}
static void OnTextChanged(BindableObject bindable, object oldValue, object newValue)
{
//Do stuff
}
So in my project I have a few textBoxes that hold the coordinates of two corners (Latitude & Longitude). The textBoxes are updated by a timer (which gets a value from a server and sets the textBoxes if the value received is different from the current value). Problem is, I want the textBoxes to be available for manual editing; However if I'm in the middle of typing the number and the timer checks the current value he sees that it's a different thing from what the server returned and changes it immediately. Is there a way to check if the textBox is being edited at the moment, or a better way to solve this solution?
code (samples, the code is the same for the two corners):
if (northEastLatitude != double.Parse(neLatTB.Text)) //neLatTB is the textBox
neLatTB.Text = northEastLatitude.ToString();
else //No answer returned from the server so we need to reset the textBoxes
{
northEastLatitude = 0;
northEastLongitude = 0;
if(neLatTB.Text != "0")
neLatTB.Text = northEastLatitude.ToString();
if(neLngTB.Text != "0")
neLngTB.Text = northEastLongitude.ToString();
}
in addition, I have functions for TextChanged events for all of the textBoxes (so that when I set the coordinates manually it uploads them to the server). Is there any way to prevent this function from being called whenever I press the dot key? apparently it calls the event too (marks the ending of the text entering).
It really depends on your design but if you want to use TextBox to show updatable values and also make it possible to edit you have to suppress code from your timer to execute. WinForms TextBox doesn't have an option to show you if text is changing programmatically or by user interaction. You have to somehow make it by yourself.
There is plenty of ways to do that of courde. One way is to use Enter/Leave events to detect when your TextBox gets or loses focus. But there will be a need to click somwhere out from the control after edit.
Another one, and probably desired by you would be using TextChanged event preventing your timer from updating field until text in TextBox will be typed in full. I would do it something like that:
Fisrtly I would declare two bool variables for blocking parts of code from execution:
private bool _isDirty; // used when user types text directly
private bool _suppresTextChanged; // used when timer updates value programmatically
After that I would write TextBox.TextChanged event listener:
private void neLatTBTextChanged(object sender, EventArgs args)
{
if(_suppressTextChanged)
return;
_isDirty = true; // toggle dirty state
if(/* text has good format */)
{
// Upload changes to server
_isDirty = false; // end manual edit mode
}
}
And inside timer method i would set:
_suppresTextChanged = true; // on the beginning
if (northEastLatitude != double.Parse(neLatTB.Text)) //neLatTB is the textBox
neLatTB.Text = northEastLatitude.ToString();
else //No answer returned from the server so we need to reset the textBoxes
{
northEastLatitude = 0;
northEastLongitude = 0;
if(neLatTB.Text != "0")
neLatTB.Text = northEastLatitude.ToString();
if(neLngTB.Text != "0")
neLngTB.Text = northEastLongitude.ToString();
}
_suppresTextChanged = false; // after edit was made
Personally i think this design can lead to a lot of problems (consider what to do when user stops typing and leave the TextBox in _isDirty state etc...). Instead of using just TextBox I would add a Label to store data from timer (and probably data the user will type) and left TextBox just for entering user specific values.
Right I have got a list box which contains a list of tracks and when the track is pressed it moves to a second list box, what I now need to happen is have the first item that's in the second list box move automatic to a text box.
This is my current code for the first move
private void genreListBox_DoubleClick(object sender, EventArgs e)
{
playlistListBox.Items.Add(genreListBox.SelectedItem);
}
I am thinking it should be something like this
presentlyPlayingTextBox.AppendText(playlistListBox.);
But I'm not sure how to add the first line without clicking it.
I have tried this but I get an error for the value.
presentlyPlayingTextBox.Text = playlistListBox.SelectedItem.Value;
Normally you would use something like the 'SelectedIndexChanged' or 'SelectedValueChanged' action of a listbox, otherwise events like DoubleClick will fail if the keyboard is used to change the selection.
Also that event should be triggered on the second listbox when it is changed by the first.
EDIT:
On a standard Listbox, there is no .SelectedItem.Value, only .SelectedItem.
However as a listbox holds objects, not just text, you need to say you want the text value.
presentlyPlayingTextBox.Text = playlistListBox.SelectedItem.ToString();
I don't know if I fully understand your question, but if you're just attempting to move the first item from ListBox_2 to a textbox, would the following work?
presentlyPlayingTextBox.Text = playlistListBox.Items[0]?.Value; // C# >= 6
presentlyPLayingTextBox.Text = ((playlistListBox.Items == null) ? playlistListBox.Items[0].Value : "" ); // C# < 6
You could also create your own delegate/event that would fire when the user did some action.
I am using ScintillaNET to make a basic IntelliSense editor. However, I have a problem when I call _editor.CallTip.Show("random text") in the AutoCompleteAccepted Event.
If I type pr for example, and scroll and select printf in the drop-down list, it goes to my AutoCompleteAccepted event and when I call the CallTip.Show, the rest of the word does not get added (however, without that CallTip code, the rest of the word is filled).
So, if I typed pr then it stays pr and I get my CallTip. How do I make sure the rest of the word gets inserted AND the CallTip shows?
Is the AutoCompleteAccepted Event not the right place to call it? If so, where should I call the CallTip.Show so that it works side-by-side with my AutoComplete?
Finally figured it out! The AutoCompleteAccepted Event isn't the right place to put CallTip.Show
What is going on is the fact that when AutoCompleteAccepted Event is called and you add text to the ScintillaNET control, it takes time for the UI to update and so, when you call to show the CallTip, it interferes with the text being inserted into the control.
The better way to do it is to call CallTip.Show in the TextChanged event, as they you know that the text has been inserted when the AutoCompleteAccepted Event was called.
It would now look something like this:
String calltipText = null; //start out with null calltip
...
private void Editor_TextChanged(object sender, EventArgs e)
{
if (calltipText != null)
{
CallTip.Show(calltipText); //note, you may want to assign a position
calltipText = null; //reset string
}
...
}
...
private void Editor_AutoCompleteAccepted(object sender, AutoCompleteAcceptedEventArgs e)
{
if (e.Text == "someThing")
{
/* Code to add text to control */
...
calltipText = "someKindOFText"; //assign value to calltipText
}
}
That is essentially what can be done to ensure the AutoComplete fills correctly and you get the CallTip to show.
Just note, that the CallTip MAY end up in unintended places, so it is recommended to set the value of where you want the CallTip to show up
In my app, I have a group of 3d objects and they're exposed to the user through a TreeView. When a user selects an item in the TreeView, an SelectedItemChanged event is fired, the corresponding 3d object is set to be selected and is highlighted in the 3d render window. This works fine.
What I'm having trouble with is the reverse. In a section of my code, I programatically set the selected 3d object in the scene. I want to reflect the currently selected object in the TreeView, so I run through the items until I find the corresponding one. But once I get to it, I can't find a way to make the item appear selected without having SelectedItemChanged being called, which is not what I want.
Is there a way to do this?
Thanks!
I take it you want to suppress the code in your event-handler? If so, a common way of doing this is with a boolean flag (or sometimes an int counter):
bool updatingSelected;
void SomeHandler(object sender, EventArgs args) { // or whatever
if(updatingSelected) return;
//...
}
void SomeCode() {
bool oldFlag = updatingSelected;
updatingSelected = true;
try {
// update the selected item
} finally {
updatingSelected = oldFlag;
}
}
Would it be appropriate to remove the TreeView's SelectedItemChanged event handler temporarily, and re-add it once you've performed the necessary operations? I haven't tried it myself, but it's the only other thing I can think of (Marc Gravell beat me to my original answer - I've done THAT before ;) ).
Good luck!