Why won't my C++/CLI tooltip appear? - windows

I have some validation code which should display the max / min of a control when a bad value is entered.
In my constructor I do this:
m_wndToolTip = gcnew ToolTip(this->components);
m_wndToolTip->AutoPopDelay = 5000;
m_wndToolTip->InitialDelay = 10;
m_wndToolTip->ReshowDelay = 250;
m_wndToolTip->ShowAlways = true;// Force the ToolTip text to be displayed whether or not the form is active.
This is my validation reflection code:
void MyGUI::IndicateValidationResult(Windows::Forms::Control^ control, bool isValid, String^ invalidReason)
{
// If the validation failed, make the background red. If not, turn it white.
if( isValid )
{
control->BackColor = Drawing::Color::White;
m_wndToolTip->Hide(control);
}
else
{
control->BackColor = Drawing::Color::LightCoral;
m_wndToolTip->Show(invalidReason, control);
}
}
...which is called from varous ValueChanged methods in my text boxes. I've tried using show and also a combination of SetToolTip and active = true and nothing seems to work.
I've seen another question asking about tooltips and have tried setting a nearby label in the call to show but that doesn't fix it either. The tooltip is a member variable in my System::Windows::Forms::Form derived form to stop it going out of scope.
Am I missing something obvious?

Your code worked fine when I tried it, there's no obvious mistake that I can see. I called it like this, using a Validating event of a text box:
bool ok;
System::Void textBox1_Validating(System::Object^ sender, System::ComponentModel::CancelEventArgs^ e) {
e->Cancel = !ok;
IndicateValidationResult(textBox1, ok, "invalid");
ok = !ok;
}
Beware that ToolTip can be cranky. The native Windows component has a "feature" that prevents a tooltip from showing again when it timed out before. The ErrorProvider component is a better mouse trap to get this done.

Related

Xamarin, how can I gain a completed state from a command?

I have a ListView and am using the SelectedItem to call a command and show a modal view.
However, I have an issue where the user can tap multiple times on the listview row and multiple modal views are shown before the view has loaded. Granted this only happens on slower devices.
This is is caused because the command doesn't have any call back.
I wouldn't normally paste code here, but in this case I thought it was more descriptive to provide a screen shot.
I've looked into the AsyncCommands but these seem to be used more to handle errors.
I'm currently thinking about a subscribe approach which is triggered when the modal is exited, however I think there must be another way I haven't thought of.
Can you try using a Boolean as IsSelected & make IsSelected true when user clicks an item from list & change your condition in setter as below. When your operations are done reset the flag.
This was, there wont not be any duplication of modals. This is what I understood from your question, if there's something else, please let me know.
if( _locationAssetSelected || !IsSelected )
{
IsSelected = true;
_locationAssetSelected = value;
..... //your code
_locationAssetSelected = null;
IsSelected = false;
}
You could move the logic to the command to make sure it doesn't execute multiple times. This is a snippet on the sample/template Forms app which uses this method as a command. Lock seems unnecessary.
async void OnItemSelected(Item item)
{
//lock (selectLock)
//{
if (item == null || selectionOn)
return;
selectionOn = true;
//}
System.Diagnostics.Debug.WriteLine($"{item.Text} selected");
// This will push the ItemDetailPage onto the navigation stack
await Shell.Current.GoToAsync($"{nameof(ItemDetailPage)}?{nameof(ItemDetailViewModel.ItemId)}={item.Id}");
selectionOn = false;
}

NativeScript TextField canPerformActionWithSender

I have a custom keyboard (made from buttons) in my app and I'm using it to populate a numeric value into a TextField. When a button is pressed, I set the text of the TextField while sanitizing the data — making sure there's only 1 decimal, no letters are entered, etc.
However, I'm now trying to detect when a user attempts to paste into the field so I can either prevent it entirely or sanitize the pasted text before allowing it to be pasted.
The approach I've taken so far is to try to implement the canPerformActionWithSender method on a NativeScript TextField.
I've tried the following (I'm using NativeScript Vue):
<TextField
ref="amount"
hint="$0.00"
#loaded="onTextFieldLoaded"
#unloaded="onTextFieldUnloaded" />
And...
onTextFieldLoaded(event) {
let textField = event.object
textField.focus()
nativeView.canPerformActionWithSender = (action, sender) => {
// `action` may be 'paste' so I can handle that action here
}
}
But this doesn't work. Is there an easy way to accomplish this without creating a custom component?
I was able to solve this with the following:
UITextField.prototype.canPerformActionWithSender = function (action, sender) {
return false;
}
This will disable the copy/paste/etc. menu completely. You can be more specific and check the action to only disable certain functionality if you like.
UITextField.prototype.canPerformActionWithSender = function (action, sender) {
if (action == 'paste:') {
return false;
}
return true;
}

Unity onClick.addlistener not working

I load a Canvas prefab at runtime when an event occurs. The canvas simply has a Panel inside it, which in turn has 2 buttons. I'm trying to add OnClick events to both these buttons in the script, but it only works for the first button somehow!
I have the following two lines of code one after the other:
GameObject.Find("RestartButton").GetComponent<Button>().onClick.AddListener(() => RestartClicked());
GameObject.Find("ViewButton").GetComponent<Button>().onClick.AddListener(() => ViewClicked());
The callback only works for the RestartButton, and not for the ViewButton.
It may well be a very small thing, but I searched Google and Bing extensively and remain clueless, so any help would be appreciated.
Thanks!
Edit:
The script instantiates the prefab and tries to reference the two buttons in the prefab through GameObject.Find(), given that once Instantiate is called the Canvas should be active in the heirarchy.
I also opened up the part of the code that attaches buttons to the listener for debugging. I dont think it attaches the listener at all.
void Start () {
SetupScene();
var prefab = Resources.Load("RestartOrViewPrefab");
if (prefab == null)
{
Debug.LogAssertion("Prefab missing!");
return;
}
restartCanvas = (GameObject)Instantiate(prefab);
Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => ViewToggle());
Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
btn2.onClick.AddListener(() => RestartClicked());
}
private void RestartClicked()
{
Debug.Log("RESTARTING");
SetupScene();
}
private void ViewToggle()
{
Debug.Log("TOGGLE");
if (freshStart)
{
//Something here
freshStart = false;
}
else
{
//Something else here
freshStart = true;
}
}
So I took two days to solve my problem. Apparently, doing a GameObject.Find() for a GameObject within a prefab that you just instantiated doesn't work. We always need to use the GameObject that the Instantiate() method returns to find any component within the prefab.
The code I used to make my scene work may not be the best solution if your prefab is very big/complex (say you have 15 buttons and need to do something with one), but it sure does work. :)
I replaced the following lines of code:
Button btn = GameObject.Find("ViewButton").GetComponent<Button>();
btn.onClick.RemoveAllListeners();
btn.onClick.AddListener(() => ViewToggle());
Button btn2 = GameObject.Find("RestartButton").GetComponent<Button>();
btn2.onClick.AddListener(() => RestartClicked());
With the following lines of code:
Button[] buttons = restartCanvas.GetComponentsInChildren<Button>();
foreach(Button but in buttons)
{
if(but.gameObject.name == "RestartButton")
but.onClick.AddListener(() => RestartClicked());
else if(but.gameObject.name == "ViewButton")
but.onClick.AddListener(() => ViewToggle());
}
So I just reused the restartCanvas that I got a reference to.
restartCanvas = (GameObject)Instantiate(prefab);
Hope this helps someone. :)
I answered this on another post, but I'll answer it here for people that still need this info.
The GameObject your instantiated button is a child of must have a CanvasRenderer component on it.
I'm not sure why this works, but it does.
Once the parent of the button GameObject has the CanvasRenderer on it, you can call myButton.onClick.AddListener(() => MyMethod(MyArgs)); as you normally would.
Ok make sure you are not getting any null reference error, and check tht spelling of you buttons , output some debug logs in your second function to see if its even reaching there

Kendo Grid: Removing dirty cell indicators

I have been looking at a way to save off my client side edited grid data automatically when the user changes to another row (just like in access, sql management studio etc). It really seems to be a bit of a challenge to do.
One scheme was to use the data source sync, but this ha the problem of loosing our cell position (it always jumped to cell 0, 0).
I have been shown some clever work arounds (go back to the cell after the case, which by the way is hugely appreciated thanks),
but it after some lengthy testing (by myself and others) seemed to be a little "glitchy" (perhaps I just need to work on this more)
At any rate, I wanted to explore perhaps not using this datasource sync and perhaps just do the server side calls "manually" (which is a bit is a pity, but if that's what we need to do, so be it). If I do this, I would want to reset the cell little red cell "dirty" indicators.
I thought I could use something similar to this scheme (except rather than resetting the flag, I want to unset).
So, as in the above link, I have the following..
var pendingChanges = [];
function gridEdit(e) {
var cellHeader = $("#gridID").find("th[data-field='" + e.field + "']");
if (cellHeader[0] != undefined) {
var pendingChange = new Object();
pendingChange.PropertyName = e.field;
pendingChange.ColumnIndex = cellHeader[0].cellIndex;
pendingChange.uid = e.items[0].uid;
pendingChanges.push(pendingChange);
}
}
where we call gridEdit from the datasource change..
var dataSrc = new kendo.data.DataSource({
change: function (e) {
gridEdit(e);
},
Now assuming we have a callback that detects the row change, I thought I could do the following...
// clear cell property (red indicator)
for (var i = 0; i < pendingChanges.length; i++) {
var row = grid.tbody.find("tr[data-uid='" + pendingChanges[i].uid + "']");
var cell = row.find("td:eq(" + pendingChanges[i].ColumnIndex + ")");
if (cell.hasClass("k-dirty-cell")) {
cell.removeClass("k-dirty-cell");
console.log("removed dirty class");
}
}
pendingChanges.length = 0;
// No good, we loose current cell again! (sigh..)
//grid.refresh();
When this didn't work, I also tried resetting the data source dirty flag..
// clear dirty flag from the database
var dirtyRows = $.grep(vm.gridData.view(),
function (item) {
return item.dirty == true;
})
if (dirtyRows && dirtyRows.length > 0) {
dirtyRows[0].dirty = false;
}
demo here
After none of the above worked, I tried the grid.refresh(), but this has the same problem as the datasource sync (we loose our current cell)
Would anyone have any idea how I can clear this cell indicator, without refreshing the whole grid that seems to totally loose our editing context?
Thanks in advance for any help!
Css :
.k-dirty-clear {
border-width:0;
}
Grid edit event :
edit: function(e) {
$("#grid .k-dirty").addClass("k-dirty-clear"); //Clear indicators
$("#grid .k-dirty").removeClass("k-dirty-clear"); //Show indicators
}
http://jsbin.com/celajewuwe/2/edit
Simple solution for resolve that problem is to override the color of the "flag" to transparent.
just override the ".k-dirty" class (border-color)
just adding the above lines to your css
CSS:
//k-dirty is the class that kendo grid use for mark edited cells that not saved yet.
//we override that class cause we do not want the red flag
.k-dirty {
border-color:transparent transparent transparent transparent;
}
This can also be done by applying the below style,
<style>
.k-dirty{
display: none;
}
</style>

how to dismiss the dropdown list of an autocompletebox in windows phone 7

is there anyway to programmatically dismiss the drop-down list of an autocompletebox? my use case is as follows.
MainPage.xaml passes a value to SearchPage.xaml (i.e. /SearchPage.xaml?query=someText).
in SearchPage.xaml.cs, i set,
autoCompleteBox.Text = NavigationContext.QueryString["query"].
at this point, the drop-down list of suggested matches shows up. i don't want this behavior when the page is just navigated to.
i also tried the following to dismiss the drop-down list but it didn't help.
autoCompleteBox.Text = NavigationContext.QueryString["query"];
autoCompleteBox.IsDropDownOpen = false;
the drop-down list seems to go away from the AutoCompleteBox when it loses focuses, but i don't see a property/field to set to make it lose focus.
any help is appreciated.
well, i tinkered a bit and came up with a kludge. in the constructor of SearchPage.xaml.cs i have the following code.
autoCompleteBox.TextFilter += DummyFilter;
autoCompleteBox.GotFocus += (s,args) => {
if(!isAutoCompleteBoxInit) {
autoCompleteBox.TextFilter -= DummyFilter;
autoCompleteBox.TextFilter += RealFilter;
}
}
DummyFilter looks like the following.
bool DummyFilter(string search, string value) { return false; }
RealFilter looks like the following.
bool RealFilter(string search, string value) {
if(null != value) return value.ToLower().StartsWith(search.ToLower());
}
in my OnNavigatedTo method, is where i set, autoCompleteBox.Text = NavigationContext.QueryString["query"]. so when i do this now, the DummyFilter will always return false, so the drop-down list goes away. when the user focuses in on the AutoCompleteBox, i check if the correct Filter was already attached to the TextFilter property, if not, then i do a switch.
hope this helps some of you.
Is there any other focusable control on the page? Just set the focus somewhere else, and your problem should be solved.
When you have changed the text of the AutoCompleteBox the dropdown will open. Only when the user has changed the text and there is a match then the dropdown will close.
Just change userInitiated to true and when there is a match the dropdown will close.
private void UpdateTextCompletion(bool userInitiated)
{
userInitiated = true; ...

Resources