How to slow down or stop key presses in XNA - c#

I've begun writing a game using XNA Framework and have hit some simple problem I do not know how to solve correctly.
I'm displaying a menu using Texture2D and using the keyboard (or gamepad) I change the menu item that is selected. My problem is that the current function used to toggle between menu items is way too fast. I might click the down button and it will go down 5 or 6 menu items (due to the fact that Update() is called many time thus updating the selected item).
ex.
(> indicate selected)
> MenuItem1
MenuItem2
MenuItem3
MenuItem4
MenuItem5
I press the down key for just a second), then I have this state:
MenuItem1
MenuItem2
MenuItem3
> MenuItem4
MenuItem5
What I want is (until I press the key again)
MenuItem1
> MenuItem2
MenuItem3
MenuItem4
MenuItem5
What I am looking for is a way to either have the player click the up/down key many time in order to go from one menu item to the other, or to have some sort of minimum wait time before going to the next menu item.

the best way to implement this is to cache the keyboard/gamepad state from the update statement that just passed.
KeyboardState oldState;
...
var newState = Keyboard.GetState();
if (newState.IsKeyDown(Keys.Down) && !oldState.IsKeyDown(Keys.Down))
{
// the player just pressed down
}
else if (newState.IsKeyDown(Keys.Down) && oldState.IsKeyDown(Keys.Down))
{
// the player is holding the key down
}
else if (!newState.IsKeyDown(Keys.Down) && oldState.IsKeyDown(Keys.Down))
{
// the player was holding the key down, but has just let it go
}
oldState = newState;
In your case, you probably only want to move "down" in the first case above, when the key was just pressed.

I've built a (large) class that helps a lot with any and all XNA input related tasks, it makes what you're asking for easy.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace YourNamespaceHere
{
/// <summary>
/// an enum of all available mouse buttons.
/// </summary>
public enum MouseButtons
{
LeftButton,
MiddleButton,
RightButton,
ExtraButton1,
ExtraButton2
}
public class InputHelper
{
private GamePadState _lastGamepadState;
private GamePadState _currentGamepadState;
#if (!XBOX)
private KeyboardState _lastKeyboardState;
private KeyboardState _currentKeyboardState;
private MouseState _lastMouseState;
private MouseState _currentMouseState;
#endif
private PlayerIndex _index = PlayerIndex.One;
private bool refreshData = false;
/// <summary>
/// Fetches the latest input states.
/// </summary>
public void Update()
{
if (!refreshData)
refreshData = true;
if (_lastGamepadState == null && _currentGamepadState == null)
{
_lastGamepadState = _currentGamepadState = GamePad.GetState(_index);
}
else
{
_lastGamepadState = _currentGamepadState;
_currentGamepadState = GamePad.GetState(_index);
}
#if (!XBOX)
if (_lastKeyboardState == null && _currentKeyboardState == null)
{
_lastKeyboardState = _currentKeyboardState = Keyboard.GetState();
}
else
{
_lastKeyboardState = _currentKeyboardState;
_currentKeyboardState = Keyboard.GetState();
}
if (_lastMouseState == null && _currentMouseState == null)
{
_lastMouseState = _currentMouseState = Mouse.GetState();
}
else
{
_lastMouseState = _currentMouseState;
_currentMouseState = Mouse.GetState();
}
#endif
}
/// <summary>
/// The previous state of the gamepad.
/// Exposed only for convenience.
/// </summary>
public GamePadState LastGamepadState
{
get { return _lastGamepadState; }
}
/// <summary>
/// the current state of the gamepad.
/// Exposed only for convenience.
/// </summary>
public GamePadState CurrentGamepadState
{
get { return _currentGamepadState; }
}
/// <summary>
/// the index that is used to poll the gamepad.
/// </summary>
public PlayerIndex Index
{
get { return _index; }
set {
_index = value;
if (refreshData)
{
Update();
Update();
}
}
}
#if (!XBOX)
/// <summary>
/// The previous keyboard state.
/// Exposed only for convenience.
/// </summary>
public KeyboardState LastKeyboardState
{
get { return _lastKeyboardState; }
}
/// <summary>
/// The current state of the keyboard.
/// Exposed only for convenience.
/// </summary>
public KeyboardState CurrentKeyboardState
{
get { return _currentKeyboardState; }
}
/// <summary>
/// The previous mouse state.
/// Exposed only for convenience.
/// </summary>
public MouseState LastMouseState
{
get { return _lastMouseState; }
}
/// <summary>
/// The current state of the mouse.
/// Exposed only for convenience.
/// </summary>
public MouseState CurrentMouseState
{
get { return _currentMouseState; }
}
#endif
/// <summary>
/// The current position of the left stick.
/// Y is automatically reversed for you.
/// </summary>
public Vector2 LeftStickPosition
{
get
{
return new Vector2(
_currentGamepadState.ThumbSticks.Left.X,
-CurrentGamepadState.ThumbSticks.Left.Y);
}
}
/// <summary>
/// The current position of the right stick.
/// Y is automatically reversed for you.
/// </summary>
public Vector2 RightStickPosition
{
get
{
return new Vector2(
_currentGamepadState.ThumbSticks.Right.X,
-_currentGamepadState.ThumbSticks.Right.Y);
}
}
/// <summary>
/// The current velocity of the left stick.
/// Y is automatically reversed for you.
/// expressed as:
/// current stick position - last stick position.
/// </summary>
public Vector2 LeftStickVelocity
{
get
{
Vector2 temp =
_currentGamepadState.ThumbSticks.Left -
_lastGamepadState.ThumbSticks.Left;
return new Vector2(temp.X, -temp.Y);
}
}
/// <summary>
/// The current velocity of the right stick.
/// Y is automatically reversed for you.
/// expressed as:
/// current stick position - last stick position.
/// </summary>
public Vector2 RightStickVelocity
{
get
{
Vector2 temp =
_currentGamepadState.ThumbSticks.Right -
_lastGamepadState.ThumbSticks.Right;
return new Vector2(temp.X, -temp.Y);
}
}
/// <summary>
/// the current position of the left trigger.
/// </summary>
public float LeftTriggerPosition
{
get { return _currentGamepadState.Triggers.Left; }
}
/// <summary>
/// the current position of the right trigger.
/// </summary>
public float RightTriggerPosition
{
get { return _currentGamepadState.Triggers.Right; }
}
/// <summary>
/// the velocity of the left trigger.
/// expressed as:
/// current trigger position - last trigger position.
/// </summary>
public float LeftTriggerVelocity
{
get
{
return
_currentGamepadState.Triggers.Left -
_lastGamepadState.Triggers.Left;
}
}
/// <summary>
/// the velocity of the right trigger.
/// expressed as:
/// current trigger position - last trigger position.
/// </summary>
public float RightTriggerVelocity
{
get
{
return _currentGamepadState.Triggers.Right -
_lastGamepadState.Triggers.Right;
}
}
#if (!XBOX)
/// <summary>
/// the current mouse position.
/// </summary>
public Vector2 MousePosition
{
get { return new Vector2(_currentMouseState.X, _currentMouseState.Y); }
}
/// <summary>
/// the current mouse velocity.
/// Expressed as:
/// current mouse position - last mouse position.
/// </summary>
public Vector2 MouseVelocity
{
get
{
return (
new Vector2(_currentMouseState.X, _currentMouseState.Y) -
new Vector2(_lastMouseState.X, _lastMouseState.Y)
);
}
}
/// <summary>
/// the current mouse scroll wheel position.
/// See the Mouse's ScrollWheel property for details.
/// </summary>
public float MouseScrollWheelPosition
{
get
{
return _currentMouseState.ScrollWheelValue;
}
}
/// <summary>
/// the mouse scroll wheel velocity.
/// Expressed as:
/// current scroll wheel position -
/// the last scroll wheel position.
/// </summary>
public float MouseScrollWheelVelocity
{
get
{
return (_currentMouseState.ScrollWheelValue - _lastMouseState.ScrollWheelValue);
}
}
#endif
/// <summary>
/// Used for debug purposes.
/// Indicates if the user wants to exit immediately.
/// </summary>
public bool ExitRequested
{
#if (!XBOX)
get
{
return (
(IsCurPress(Buttons.Start) &&
IsCurPress(Buttons.Back)) ||
IsCurPress(Keys.Escape));
}
#else
get { return (IsCurPress(Buttons.Start) && IsCurPress(Buttons.Back)); }
#endif
}
/// <summary>
/// Checks if the requested button is a new press.
/// </summary>
/// <param name="button">
/// The button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected button is being
/// pressed in the current state but not the last state.
/// </returns>
public bool IsNewPress(Buttons button)
{
return (
_lastGamepadState.IsButtonUp(button) &&
_currentGamepadState.IsButtonDown(button));
}
/// <summary>
/// Checks if the requested button is a current press.
/// </summary>
/// <param name="button">
/// the button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected button is being
/// pressed in the current state and in the last state.
/// </returns>
public bool IsCurPress(Buttons button)
{
return (
_lastGamepadState.IsButtonDown(button) &&
_currentGamepadState.IsButtonDown(button));
}
/// <summary>
/// Checks if the requested button is an old press.
/// </summary>
/// <param name="button">
/// the button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected button is not being
/// pressed in the current state and is being pressed in the last state.
/// </returns>
public bool IsOldPress(Buttons button)
{
return (
_lastGamepadState.IsButtonDown(button) &&
_currentGamepadState.IsButtonUp(button));
}
#if (!XBOX)
/// <summary>
/// Checks if the requested key is a new press.
/// </summary>
/// <param name="key">
/// the key to check.
/// </param>
/// <returns>
/// a bool that indicates whether the selected key is being
/// pressed in the current state and not in the last state.
/// </returns>
public bool IsNewPress(Keys key)
{
return (
_lastKeyboardState.IsKeyUp(key) &&
_currentKeyboardState.IsKeyDown(key));
}
/// <summary>
/// Checks if the requested key is a current press.
/// </summary>
/// <param name="key">
/// the key to check.
/// </param>
/// <returns>
/// a bool that indicates whether the selected key is being
/// pressed in the current state and in the last state.
/// </returns>
public bool IsCurPress(Keys key)
{
return (
_lastKeyboardState.IsKeyDown(key) &&
_currentKeyboardState.IsKeyDown(key));
}
/// <summary>
/// Checks if the requested button is an old press.
/// </summary>
/// <param name="key">
/// the key to check.
/// </param>
/// <returns>
/// a bool indicating whether the selectde button is not being
/// pressed in the current state and being pressed in the last state.
/// </returns>
public bool IsOldPress(Keys key)
{
return (
_lastKeyboardState.IsKeyDown(key) &&
_currentKeyboardState.IsKeyUp(key));
}
/// <summary>
/// Checks if the requested mosue button is a new press.
/// </summary>
/// <param name="button">
/// teh mouse button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected mouse button is being
/// pressed in the current state but not in the last state.
/// </returns>
public bool IsNewPress(MouseButtons button)
{
switch (button)
{
case MouseButtons.LeftButton:
return (
_lastMouseState.LeftButton == ButtonState.Released &&
_currentMouseState.LeftButton == ButtonState.Pressed);
case MouseButtons.MiddleButton:
return (
_lastMouseState.MiddleButton == ButtonState.Released &&
_currentMouseState.MiddleButton == ButtonState.Pressed);
case MouseButtons.RightButton:
return (
_lastMouseState.RightButton == ButtonState.Released &&
_currentMouseState.RightButton == ButtonState.Pressed);
case MouseButtons.ExtraButton1:
return (
_lastMouseState.XButton1 == ButtonState.Released &&
_currentMouseState.XButton1 == ButtonState.Pressed);
case MouseButtons.ExtraButton2:
return (
_lastMouseState.XButton2 == ButtonState.Released &&
_currentMouseState.XButton2 == ButtonState.Pressed);
default:
return false;
}
}
/// <summary>
/// Checks if the requested mosue button is a current press.
/// </summary>
/// <param name="button">
/// the mouse button to be checked.
/// </param>
/// <returns>
/// a bool indicating whether the selected mouse button is being
/// pressed in the current state and in the last state.
/// </returns>
public bool IsCurPress(MouseButtons button)
{
switch (button)
{
case MouseButtons.LeftButton:
return (
_lastMouseState.LeftButton == ButtonState.Pressed &&
_currentMouseState.LeftButton == ButtonState.Pressed);
case MouseButtons.MiddleButton:
return (
_lastMouseState.MiddleButton == ButtonState.Pressed &&
_currentMouseState.MiddleButton == ButtonState.Pressed);
case MouseButtons.RightButton:
return (
_lastMouseState.RightButton == ButtonState.Pressed &&
_currentMouseState.RightButton == ButtonState.Pressed);
case MouseButtons.ExtraButton1:
return (
_lastMouseState.XButton1 == ButtonState.Pressed &&
_currentMouseState.XButton1 == ButtonState.Pressed);
case MouseButtons.ExtraButton2:
return (
_lastMouseState.XButton2 == ButtonState.Pressed &&
_currentMouseState.XButton2 == ButtonState.Pressed);
default:
return false;
}
}
/// <summary>
/// Checks if the requested mosue button is an old press.
/// </summary>
/// <param name="button">
/// the mouse button to check.
/// </param>
/// <returns>
/// a bool indicating whether the selected mouse button is not being
/// pressed in the current state and is being pressed in the old state.
/// </returns>
public bool IsOldPress(MouseButtons button)
{
switch (button)
{
case MouseButtons.LeftButton:
return (
_lastMouseState.LeftButton == ButtonState.Pressed &&
_currentMouseState.LeftButton == ButtonState.Released);
case MouseButtons.MiddleButton:
return (
_lastMouseState.MiddleButton == ButtonState.Pressed &&
_currentMouseState.MiddleButton == ButtonState.Released);
case MouseButtons.RightButton:
return (
_lastMouseState.RightButton == ButtonState.Pressed &&
_currentMouseState.RightButton == ButtonState.Released);
case MouseButtons.ExtraButton1:
return (
_lastMouseState.XButton1 == ButtonState.Pressed &&
_currentMouseState.XButton1 == ButtonState.Released);
case MouseButtons.ExtraButton2:
return (
_lastMouseState.XButton2 == ButtonState.Pressed &&
_currentMouseState.XButton2 == ButtonState.Released);
default:
return false;
}
}
#endif
}
}
Just copy it into a separate class fie and move it to your namespace, then declare one (inputHelper variable), initialize it in the initialiaze portion, and call inputHelper.Update() in your update loop before the update logic. Then whenever you need something related to input, just use the InputHelper! for instance, in your situation, you would use InputHelper.IsNewPress([type of input button/key here]) to check if you want to move the menu item down or up. For this example: inputHelper.IsNewPress(Keys.Down)

A nice way of dealing with this kind of thing is to store a counter for each key you're interested in, which you increment every frame if the key is down, and reset to 0 if it's up.
The advantage of this is that you can then test for both the absolute state of the key (if the counter is non-zero the key is down) and also easily check if it's just been pressed this frame for menus and the like (counter is 1). Plus key repeat becomes easy (counter % repeat delay is zero).

If your application is for a Windows machine, I've had great success using this event driven class that I found here: gamedev.net forum post
It handles typical key presses and the short pauses before the repeating starts, just like normal text entry in a Windows application. Also included is mouse move/wheel events.
You can subscribe to the events, for example, using the following code:
InputSystem.KeyDown += new KeyEventHandler(KeyDownFunction);
InputSystem.KeyUp += new KeyEventHandler(KeyUpFunction);
Then in the methods themselves:
void KeyDownFunction(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.F)
facepalm();
}
void KeyUpFunction(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.F)
release();
}
...and so forth. It really is a great class. I've found it's flexibility much improved over XNA's default keyboard handling. Good Luck!

I thought the previous answers were a bit over-complicated, so I'm giving this one here...
Copy the KeyPress class below in a new file, declare the KeyPress variables, initialize them in your Initialize() method. From there you can do if ([yourkey].IsPressed()) ...
Note: this answer works only for Keyboard input, but it should be easily ported to Gamepad or any other input. I think keeping the code for the different types of input separate is better.
public class KeyPress
{
public KeyPress(Keys Key)
{
key = Key;
isHeld = false;
}
public bool IsPressed { get { return isPressed(); } }
public static void Update() { state = Keyboard.GetState(); }
private Keys key;
private bool isHeld;
private static KeyboardState state;
private bool isPressed()
{
if (state.IsKeyDown(key))
{
if (isHeld) return false;
else
{
isHeld = true;
return true;
}
}
else
{
if (isHeld) isHeld = false;
return false;
}
}
}
Usage:
// Declare variable
KeyPress escape;
// Initialize()
escape = new KeyPress(Keys.Escape)
// Update()
KeyPress.Update();
if (escape.IsPressed())
...
I might be wrong, but I think my answer is easier on resources than the accepted answer and also more readable!

You could store in integer value time from last key pressed (left,right...) and if this time is bigger than some limit you could poll for new key pressed. However this could be done only for menu, because in-game you would need that information immediately.

What you can also do is make yourself a functions combining KyeUp and KeyDown that tells you when the key has been pressed once, only in 1 loop of the update, so that it only works everytime you press the key again.

Ok, I've figured it out. First, I added a
private Keys keyPressed = Keys.None;
and in my Update() method, I do the following:
KeyboardState keyboardState = Keyboard.GetState();
if (keyboardState.IsKeyUp(keyPressed))
{
keyPressed = Keys.None;
}
if (keyboardState.IsKeyDown(keyPressed))
{
return;
}
// Some additionnal stuff is done according to direction
if (keyboardState.IsKeyDown(Keys.Up))
{
keyPressed = Keys.Up;
}
else if (keyboardState.IsKeyDown(Keys.Down))
{
keyPressed = Keys.Down;
}
It seems to be working correctly.

I save the GamePadState and KeyboardState from the previous update run. At the next update run i check for buttons that were not pressed last run, but are pressed now. Then I save the current state.
I have all of this wrapped up in a static class that I can use to query for specific buttons and/or get a list of pressed buttons since the last update. This makes it really easy to work with multiple keys simultaneously (something you certainly want in games) and it would be trivially extensible to chords.

Ranieri, what does that look like? I am having a hard time juggling these update cycles...
Hrmmm...
public static bool CheckKeyPress(Keys key)
{
return keyboardState.IsKeyUp(key) && lastKeyboardState.IsKeyDown(key);
}
SetStates() is private and it is called in the Update()
private static void SetStates()
{
lastKeyboardState = keyboardState;
keyboardState = Keyboard.GetState();
}
Here is the update...
public sealed override void Update(GameTime gameTime)
{
// Called to set the states of the input devices
SetStates();
base.Update(gameTime);
}
I've tried adding extra checks..
if (Xin.CheckKeyPress(Keys.Enter) ||
Xin.CheckButtonPress(Buttons.A))
{
if (Xin.LastKeyboardState != Xin.KeyboardState ||
Xin.LastGamePadState(PlayerIndex.One) != Xin.GamePadState(PlayerIndex.One))
{
doesn't seem to have any noticeable effects - I can't seem to slow down the menu confirmations,

Well what you could do is something like this (Also will track every key)
int[] keyVals;
TimeSpan pressWait = new TimeSpan(0, 0, 1);
Dictionary<Keys, bool> keyDowns = new Dictionary<Keys, bool>();
Dictionary<Keys, DateTime> keyTimes = new Dictionary<Keys, DateTime>();
public ConstructorNameHere
{
keyVals = Enum.GetValues(typeof(Keys)) as int[];
foreach (int k in keyVals)
{
keyDowns.Add((Keys)k, false);
keyTimes.Add((Keys)k, new DateTime()+ new TimeSpan(1,0,0));
}
}
protected override void Update(GameTime gameTime)
{
foreach (int i in keyVals)
{
Keys key = (Keys)i;
switch (key)
{
case Keys.Enter:
keyTimes[key] = (Keyboard.GetState().IsKeyUp(key)) ? ((keyDowns[key]) ? DateTime.Now + pressWait : keyTimes[key]) : keyTimes[key];
keyDowns[key] = (keyTimes[key] > DateTime.Now) ? false : Keyboard.GetState().IsKeyDown(key);
if (keyTimes[key] < DateTime.Now)
{
// Code for what happens when Keys.Enter is pressed goes here.
}
break;
}
}
By doing it this way you're able to check every key. You could also do this for just every key by create separate DateTimes and seperate bool values.

I know this is old, but how about:
Add a threadsafe dictionary:
private ConcurrentDictionary<Keys, DateTime> _keyBounceDict = new ConcurrentDictionary<Keys, DateTime>();
Then use this method to track the keys pressed and determine if there is a key bounce:
///////////////////////////////////////////////////////////////////////////////////////////
/// IsNotKeyBounce - determines if a key is bouncing and therefore not valid within
/// a certain "delay" period
///////////////////////////////////////////////////////////////////////////////////////////
private bool IsNotKeyBounce(Keys thekey, double delay)
{
bool OKtoPress = true;
if (_keyBounceDict.ContainsKey(thekey))
{
TimeSpan ts = DateTime.Now - _keyBounceDict[thekey];
if (ts.TotalMilliseconds < _tsKeyBounceTiming)
{
OKtoPress = false;
}
else
{
DateTime dummy;
_keyBounceDict.TryRemove(thekey, out dummy);
}
}
else
{
_keyBounceDict.AddOrUpdate(thekey, DateTime.Now, (key, oldValue) => oldValue);
}
return OKtoPress;
}
Here is what I put in my Update method:
if (Keyboard.GetState().IsKeyDown(Keys.W))
{
if (IsNotKeyBounce(Keys.W, 50.0)) _targetNew.Distance *= 1.1f;
}
I use 50 ms, but you could use whatever makes sense for your app or tie it to GameTime or whatever...

Related

XR button all functions

I am using XR class from Unity and trying to add all button inputs to m_SelectUsage. But unfortunately it does not take an array of values. Here in the picture as you can see, only one button can be used "Grip". Is there a way to add all the button inputs to this class?
using UnityEngine.SpatialTracking;
#if LIH_PRESENT
using UnityEngine.Experimental.XR.Interaction;
#endif
namespace UnityEngine.XR.Interaction.Toolkit
{
/// <summary>
/// <see cref="XRBaseController"/> <see cref="MonoBehaviour"/> that interprets
/// feature values on an input device in the XR input subsystem into
/// XR Interaction Interactor position, rotation, and interaction states.
/// </summary>
[AddComponentMenu("XR/XR Controller (Device-based)")]
public class XRController : XRBaseController
{
[SerializeField]
[Tooltip("The XRNode for this controller.")]
XRNode m_ControllerNode = XRNode.RightHand;
/// <summary>
/// The <see cref="XRNode"/> for this controller.
/// </summary>
public XRNode controllerNode
{
get => m_ControllerNode;
set => m_ControllerNode = value;
}
[SerializeField]
[Tooltip("The input to use for detecting a select.")]
InputHelpers.Button m_SelectUsage = InputHelpers.Button.Grip;
/// <summary>
/// The input to use for detecting a select.
/// </summary>
public InputHelpers.Button selectUsage
{
get => m_SelectUsage;
set => m_SelectUsage = value;
}
[SerializeField]
[Tooltip("The input to use for detecting activation.")]
InputHelpers.Button m_ActivateUsage = InputHelpers.Button.Trigger;
/// <summary>
/// The input to use for detecting activation.
/// </summary>
public InputHelpers.Button activateUsage
{
get => m_ActivateUsage;
set => m_ActivateUsage = value;
}
[SerializeField]
[Tooltip("The input to use for detecting a UI press.")]
InputHelpers.Button m_UIPressUsage = InputHelpers.Button.Trigger;
/// <summary>
/// The input to use for detecting a UI press.
/// </summary>
public InputHelpers.Button uiPressUsage
{
get => m_UIPressUsage;
set => m_UIPressUsage = value;
}
[SerializeField]
[Tooltip("The amount an axis needs to be pressed to trigger an interaction event.")]
float m_AxisToPressThreshold = 0.1f;
/// <summary>
/// The amount an axis needs to be pressed to trigger an interaction event.
/// </summary>
public float axisToPressThreshold
{
get => m_AxisToPressThreshold;
set => m_AxisToPressThreshold = value;
}
[SerializeField]
[Tooltip("The input to use to rotate an anchor to the Left.")]
InputHelpers.Button m_RotateAnchorLeft = InputHelpers.Button.PrimaryAxis2DLeft;
/// <summary>
/// The input to use to rotate an anchor to the Left.
/// </summary>
public InputHelpers.Button rotateObjectLeft
{
get => m_RotateAnchorLeft;
set => m_RotateAnchorLeft = value;
}
[SerializeField]
[Tooltip("The input to use to rotate an anchor to the Right.")]
InputHelpers.Button m_RotateAnchorRight = InputHelpers.Button.PrimaryAxis2DRight;
/// <summary>
/// The input to use to rotate an anchor to the Right.
/// </summary>
public InputHelpers.Button rotateObjectRight
{
get => m_RotateAnchorRight;
set => m_RotateAnchorRight = value;
}
[SerializeField]
[Tooltip("The input that will be used to translate the anchor away from the interactor.")]
InputHelpers.Button m_MoveObjectIn = InputHelpers.Button.PrimaryAxis2DUp;
/// <summary>
/// The input that will be used to translate the anchor away from the interactor.
/// </summary>
public InputHelpers.Button moveObjectIn
{
get => m_MoveObjectIn;
set => m_MoveObjectIn = value;
}
[SerializeField]
[Tooltip("The input that will be used to translate the anchor towards the interactor.")]
InputHelpers.Button m_MoveObjectOut = InputHelpers.Button.PrimaryAxis2DDown;
/// <summary>
/// The input that will be used to translate the anchor towards the interactor.
/// </summary>
public InputHelpers.Button moveObjectOut
{
get => m_MoveObjectOut;
set => m_MoveObjectOut = value;
}
#if LIH_PRESENT
[SerializeField, Tooltip("Pose provider used to provide tracking data separate from the XR Node.")]
BasePoseProvider m_PoseProvider;
/// <summary>
/// Pose provider used to provide tracking data separate from the <see cref="XRNode"/>.
/// </summary>
public BasePoseProvider poseProvider
{
get => m_PoseProvider;
set => m_PoseProvider = value;
}
#endif
InputDevice m_InputDevice;
/// <summary>
/// (Read Only) The <see cref="InputDevice"/> being used to read data from.
/// </summary>
public InputDevice inputDevice => m_InputDevice.isValid ? m_InputDevice : m_InputDevice = InputDevices.GetDeviceAtXRNode(controllerNode);
/// <inheritdoc />
protected override void UpdateTrackingInput(XRControllerState controllerState)
{
controllerState.poseDataFlags = PoseDataFlags.NoData;
#if LIH_PRESENT_V1API
if (m_PoseProvider != null)
{
if (m_PoseProvider.TryGetPoseFromProvider(out var poseProviderPose))
{
controllerState.position = poseProviderPose.position;
controllerState.rotation = poseProviderPose.rotation;
controllerState.poseDataFlags = PoseDataFlags.Position | PoseDataFlags.Rotation;
}
}
else
#elif LIH_PRESENT_V2API
if (m_PoseProvider != null)
{
var retFlags = m_PoseProvider.GetPoseFromProvider(out var poseProviderPose);
if ((retFlags & PoseDataFlags.Position) != 0)
{
controllerState.position = poseProviderPose.position;
controllerState.poseDataFlags |= PoseDataFlags.Position;
}
if ((retFlags & PoseDataFlags.Rotation) != 0)
{
controllerState.rotation = poseProviderPose.rotation;
controllerState.poseDataFlags |= PoseDataFlags.Rotation;
}
}
else
#endif
{
if (inputDevice.TryGetFeatureValue(CommonUsages.devicePosition, out controllerState.position))
{
controllerState.poseDataFlags |= PoseDataFlags.Position;
}
if (inputDevice.TryGetFeatureValue(CommonUsages.deviceRotation, out controllerState.rotation))
{
controllerState.poseDataFlags |= PoseDataFlags.Rotation;
}
}
}
/// <inheritdoc />
protected override void UpdateInput(XRControllerState controllerState)
{
controllerState.ResetFrameDependentStates();
HandleInteractionAction(m_SelectUsage, ref controllerState.selectInteractionState);
HandleInteractionAction(m_ActivateUsage, ref controllerState.activateInteractionState);
HandleInteractionAction(m_UIPressUsage, ref controllerState.uiPressInteractionState);
}
void HandleInteractionAction(InputHelpers.Button button, ref InteractionState interactionState)
{
inputDevice.IsPressed(button, out var pressed, m_AxisToPressThreshold);
if (pressed)
{
Debug.Log("Detect");
if (!interactionState.active)
{
interactionState.activatedThisFrame = true;
interactionState.active = true;
}
}
else
{
if (interactionState.active)
{
interactionState.deactivatedThisFrame = true;
interactionState.active = false;
}
}
}
/// <inheritdoc />
public override bool SendHapticImpulse(float amplitude, float duration)
{
if (inputDevice.TryGetHapticCapabilities(out var capabilities) &&
capabilities.supportsImpulse)
{
return inputDevice.SendHapticImpulse(0u, amplitude, duration);
}
return false;
}
}
}
You can overwrite XRController to accept an array for each of the input values.
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
public class MyXRController : XRController
{
[SerializeField]
InputHelpers.Button[] m_SelectUsageArray;
protected override void UpdateInput(XRControllerState controllerState)
{
// Because we use base input m_SelectUsage will still be accepted if provided
base.UpdateInput(controllerState);
// Iterate over all buttons
foreach (var selectUsage in m_SelectUsageArray)
{
HandleInteractionAction(selectUsage, ref controllerState.selectInteractionState);
}
}
}
You can overwrite other interactions in a similar manner.
Then in your GameObject, use MyXRController instead of XRController

How to disable Togglebutton from extended combobox class

I have a class that extends Combobox. In this class I can ONLY disable the togglebutton. I still want users to click into the combobox and type something in to filter its contents.
If you know any other way to destroy the togglebutton please let me know (as long as it doesn't involve recreating the template - I've tried and failed and the generated combobox template code is to large to dump in stackoverflow so I can't solve it that way. )
In the beginning I wanted to be able to toggle the togglebutton (if there less than 10 item left in the filter allow a user to click the togglebutton to show the list of items if there are more the togglebutton would disappear) . At this point I'll take any solution that shrinks, hides, moves, intentionally breaks, removes, buries alive, replaces either the togglebutton or the mouse on click event that tells the combobox that it should show its popup or anything in between that will stop this action.
This is my third question trying to find something that will work. Honestly any suggestions would be helpful (just no copy and edit the template please go to my other question where I ask help on how to implement that solution)
using Analytics_Module.Models;
using System;
using System.Collections;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
namespace Analytics_Module.UI_Components
{
class MultiselectFilteredComboBox : ComboBox
{
////
// Public Fields
////
/// <summary>
/// The search string treshold length.
/// </summary>
/// <remarks>
/// It's implemented as a Dependency Property, so you can set it in a XAML template
/// </remarks>
public static readonly DependencyProperty MinimumSearchLengthProperty =
DependencyProperty.Register(
"MinimumSearchLength",
typeof(int),
typeof(MultiselectFilteredComboBox),
new UIPropertyMetadata(3));
////
// Private Fields
////
/// <summary>
/// Caches the previous value of the filter.
/// </summary>
private string oldFilter = string.Empty;
/// <summary>
/// Holds the current value of the filter.
/// </summary>
private string currentFilter = string.Empty;
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
////
// Constructors
////
/// <summary>
/// Initializes a new instance of the FilteredComboBox class.
/// </summary>
/// <remarks>
/// You could set 'IsTextSearchEnabled' to 'false' here,
/// to avoid non-intuitive behavior of the control
/// </remarks>
public MultiselectFilteredComboBox()
{
}
////
// Properties
////
/// <summary>
/// Gets or sets the search string treshold length.
/// </summary>
/// <value>The minimum length of the search string that triggers filtering.</value>
[Description("Length of the search string that triggers filtering.")]
[Category("Filtered ComboBox")]
[DefaultValue(3)]
public int MinimumSearchLength
{
[System.Diagnostics.DebuggerStepThrough]
get
{
return (int)this.GetValue(MinimumSearchLengthProperty);
}
[System.Diagnostics.DebuggerStepThrough]
set
{
this.SetValue(MinimumSearchLengthProperty, value);
}
}
/// <summary>
/// Gets a reference to the internal editable textbox.
/// </summary>
/// <value>A reference to the internal editable textbox.</value>
/// <remarks>
/// We need this to get access to the Selection.
/// </remarks>
protected TextBox EditableTextBox
{
get
{
return this.GetTemplateChild("PART_EditableTextBox") as TextBox;
}
}
////
// Event Raiser Overrides
////
/// <summary>
/// Keep the filter if the ItemsSource is explicitly changed.
/// </summary>
/// <param name="oldValue">The previous value of the filter.</param>
/// <param name="newValue">The current value of the filter.</param>
protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
if (newValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
view.Filter += this.FilterPredicate;
}
if (oldValue != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);
view.Filter -= this.FilterPredicate;
}
base.OnItemsSourceChanged(oldValue, newValue);
}
/// <summary>
/// Confirm or cancel the selection when Tab, Enter, or Escape are hit.
/// Open the DropDown when the Down Arrow is hit.
/// </summary>
/// <param name="e">Key Event Args.</param>
/// <remarks>
/// The 'KeyDown' event is not raised for Arrows, Tab and Enter keys.
/// It is swallowed by the DropDown if it's open.
/// So use the Preview instead.
/// </remarks>
protected override void OnPreviewKeyDown(KeyEventArgs e)
{
if (e.Key == Key.Tab || e.Key == Key.Enter)
{
// Explicit Selection -> Close ItemsPanel
this.IsDropDownOpen = false;
}
else if (e.Key == Key.Escape)
{
// Escape -> Close DropDown and redisplay Filter
this.IsDropDownOpen = false;
this.SelectedIndex = -1;
this.Text = this.currentFilter;
}
else
{
if (e.Key == Key.Down)
{
// Arrow Down -> Open DropDown
this.IsDropDownOpen = true;
}
base.OnPreviewKeyDown(e);
}
// Cache text
this.oldFilter = this.Text;
}
/// <summary>
/// Modify and apply the filter.
/// </summary>
/// <param name="e">Key Event Args.</param>
/// <remarks>
/// Alternatively, you could react on 'OnTextChanged', but navigating through
/// the DropDown will also change the text.
/// </remarks>
protected override void OnKeyUp(KeyEventArgs e)
{
if (e.Key == Key.Up || e.Key == Key.Down)
{
// Navigation keys are ignored
}
else if (e.Key == Key.Tab || e.Key == Key.Enter)
{
// Explicit Select -> Clear Filter
this.ClearFilter();
}
else
{
// The text was changed
if (this.Text != this.oldFilter)
{
// Clear the filter if the text is empty,
// apply the filter if the text is long enough
if (this.Text.Length == 0 || this.Text.Length >= this.MinimumSearchLength)
{
this.RefreshFilter();
this.IsDropDownOpen = true;
// Unselect
this.EditableTextBox.SelectionStart = int.MaxValue;
}
}
base.OnKeyUp(e);
// Update Filter Value
this.currentFilter = this.Text;
}
}
/// <summary>
/// Make sure the text corresponds to the selection when leaving the control.
/// </summary>
/// <param name="e">A KeyBoardFocusChangedEventArgs.</param>
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
{
//this.ClearFilter();
//int temp = this.SelectedIndex;
//this.SelectedIndex = -1;
//this.Text = string.Empty;
//this.SelectedIndex = temp;
//base.OnPreviewLostKeyboardFocus(e);
}
////
// Helpers
////
/// <summary>
/// Re-apply the Filter.
/// </summary>
private void RefreshFilter()
{
if (this.ItemsSource != null)
{
ICollectionView view = CollectionViewSource.GetDefaultView(this.ItemsSource);
view.Refresh();
}
}
/// <summary>
/// Clear the Filter.
/// </summary>
private void ClearFilter()
{
this.currentFilter = string.Empty;
this.RefreshFilter();
}
/// <summary>
/// The Filter predicate that will be applied to each row in the ItemsSource.
/// </summary>
/// <param name="value">A row in the ItemsSource.</param>
/// <returns>Whether or not the item will appear in the DropDown.</returns>
private bool FilterPredicate(object value)
{
MultiSelectDropDownListEntry tmp = (MultiSelectDropDownListEntry)value;
// No filter, no text
if (value == null)
{
return false;
}
// No text, no filter
if (this.Text.Length == 0)
{
return true;
}
// Case insensitive search
return tmp.Name.ToString().ToLower().Contains(this.Text.ToLower());
}
}
}
Found a way.
I added this to the class
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
(((this.GetVisualChild(0) as Grid).Children)[1] as System.Windows.Controls.Primitives.ToggleButton).IsEnabled = false;
}

How to move through all controls inside controls in Asp.Net WebForm?

How to move through all controls inside Panel Web Control or any other control?
control.FindControls("name") finds only controls in the same level only
below is an answer with high speed and lower resources with multitasking
/// <summary>
/// Start from Control and move through all inside controls to check if can execute and
/// execute ctrlAction if canExecute results true
/// </summary>
/// <typeparam name="T">
/// Any Control or object inherits System.Web.UI.Control
/// </typeparam>
/// <param name="ctrl">
/// the System.Web.UI.Control to traverse from and inside
/// </param>
/// <param name="ctrlAction">
/// the action to execute on the valid control
/// </param>
/// <param name="canExecute">
/// to check if the current reached control is valid for ctrlAction execution
/// </param>
public static void ExApply<T>(
this Control ctrl, Action<T> ctrlAction, Predicate<T> canExecute = null) where T : Control
{
// if ctrl is null return null
if (ctrl == null) { return; }
// to handle multitasking on the valid controls
LinkedList<Task> taskList = new LinkedList<Task>();
// start control traverse through all controls from and inside
ctrl._exApply(canExecute, ctrlAction, taskList);
// Waiting not finished, clean and clear resources
taskList._exWaitAndDispose();
}
/// <summary>
/// Start from ControlCollection and move through all inside controls to check if can execute and
/// execute ctrlAction if canExecute results true
/// </summary>
/// <typeparam name="T">
/// Any Control or object inherits System.Web.UI.Control
/// </typeparam>
/// <param name="ctrls">
/// the System.Web.UI.ControlCollection to traverse from and inside
/// </param>
/// <param name="ctrlAction">
/// the action to execute on the valid control
/// </param>
/// <param name="canExecute">
/// to check if the current reached control is valid for ctrlAction execution
/// </param>
public static void ExApply<T>(
this ControlCollection ctrls, Action<T> ctrlAction, Predicate<T> canExecute = null)
where T : Control
{
// if ctrls is null return null
if (ctrls == null) { return; }
// to handle multitasking on the valid controls
LinkedList<Task> taskList = new LinkedList<Task>();
// start control traverse through all controls from and inside
ctrls._exApply(canExecute, ctrlAction, taskList);
// Waiting not finished, clean and clear resources
taskList._exWaitAndDispose();
}
private static void _exApply<T>(
this Control ctrl, Predicate<T> canExecute, Action<T> ctrlAction, LinkedList<Task> taskList)
where T : Control
{
// if ctrl is null no more moves needed
if (ctrl == null) { return; }
// if ctrl can be casted and has no empty id
if ((ctrl is T castedCtrl) && castedCtrl.ID.ExIsNotNone())
{
// if canExecute is null or returned true result
if (canExecute == null || (canExecute != null && canExecute(castedCtrl)))
{
// add castedCtrl as an asynchronous task
taskList.AddLast(Task.Run(() => ctrlAction(castedCtrl)));
// check first node task if completed to remove and dispose
taskList._exDisposeFirsts();
}
}
// move more deep into inside controls
if (ctrl.Controls != null && ctrl.Controls.Count > 0)
{
ctrl.Controls._exApply(canExecute, ctrlAction, taskList);
}
}
private static void _exApply<T>(
this ControlCollection ctrls, Predicate<T> canExecute, Action<T> ctrlAction,
LinkedList<Task> taskList) where T : Control
{
for (int index = 0; index < ctrls.Count; index++)
{
// move through control to validate and apply ctrlAction
ctrls[index]?._exApply(canExecute, ctrlAction, taskList);
}
}
private static void _exDisposeFirsts(this LinkedList<Task> taskList)
{
while (taskList.Count > 0 && taskList.First.Value.IsCompleted)
{
taskList.First.Value.Dispose();
taskList.RemoveFirst();
}
}
private static void _exWaitAndDispose(this LinkedList<Task> taskList)
{
taskList._exDisposeFirsts();
if (taskList.Count < 1) { return; }
Task[] tasks = new Task[taskList.Count];
taskList.CopyTo(tasks, 0);
taskList.Clear();
Task.WaitAll(tasks);
tasks.ExDispose();
}
/// <summary>
/// Smaller Size name and usage from "string.IsNullOrWhiteSpace(text)" Indicates whether a
/// specified string is null, empty, or consists only of white-space characters.
/// </summary>
/// <param name="text">The string to test</param>
/// <returns>
/// true if the value parameter is null or System.String.Empty, or if value consists
/// exclusively of white-space characters.
/// </returns>
public static bool ExIsNone(this string text) => string.IsNullOrWhiteSpace(text);
/// <summary>
/// Smaller Size name and usage from "!string.IsNullOrWhiteSpace(text)" Indicates whether a
/// specified string is not null, not empty, or not consists only of white-space characters.
/// </summary>
/// <param name="text">The string to test</param>
/// <returns>
/// true if the value parameter is not null or not System.String.Empty, or if value not consists
/// exclusively of white-space characters.
/// </returns>
public static bool ExIsNotNone(this string text) => text.ExIsNone().ExIs(false);
/// <summary>
/// Use for easier code reading instead of inverse ! character and ambiguous names
/// </summary>
/// <param name="value">value to test</param>
/// <param name="compareValue">value to compare with</param>
/// <returns>true is equal otherwise false</returns>
public static bool ExIs(this bool value, bool compareValue) => value == compareValue;

Decimal point can not enter in Silverlight's TextBox

I’m using Silverlight 5.
I’m having problem to enter decimal point in my TextBox. Every time I entered a decimal point, the cursor will always return back to the beginning of value entered in the TextBox and the decimal point will be removed.
Strange thing is that this problem only occurs when I deploy my application on IIS and running it from internet browser. The problem was NOT there when I run it from Visual Studio 2010 in debug mode.
Bellow is my XAML code for the TextBox:
<TextBox Grid.Column="2" Grid.Row="1" Text="{Binding Path=SelectedModel.MyHight,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Helper:TextBoxFilter.Filter="PositiveDecimal"/>
The Helper Class TextBoxFilter actually doing the PositiveDecimal filtering. Bellow are the classes (These are not my codes. Got it somewhere in the internet):
TextBoxFilterType.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace NumericUpdateSourceProblem
{
public enum TextBoxFilterType
{
None,
PositiveInteger,
Integer,
PositiveDecimal,
Decimal,
Alpha,
}
}
TextBoxFilter.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace NumericUpdateSourceProblem
{
public class TextBoxFilter
{
/// <summary>
/// Filter Attached Dependency Property
/// </summary>
public static readonly DependencyProperty FilterProperty =
DependencyProperty.RegisterAttached("Filter", typeof(TextBoxFilterType), typeof(TextBoxFilter),
new PropertyMetadata(OnFilterChanged));
/// <summary>
/// Gets the Filter property.
/// </summary>
public static TextBoxFilterType GetFilter(DependencyObject d)
{
return (TextBoxFilterType)d.GetValue(FilterProperty);
}
/// <summary>
/// Sets the Filter property.
/// </summary>
public static void SetFilter(DependencyObject d, TextBoxFilterType value)
{
d.SetValue(FilterProperty, value);
}
/// <summary>
/// Handles changes to the Filter property.
/// </summary>
/// <param name="d">DependencyObject</param>
/// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void OnFilterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = d as TextBox;
if (TextBoxFilterType.None != (TextBoxFilterType)e.OldValue)
{
textBox.KeyDown -= new KeyEventHandler(textBox_KeyDown);
}
if (TextBoxFilterType.None != (TextBoxFilterType)e.NewValue)
{
textBox.KeyDown += new KeyEventHandler(textBox_KeyDown);
}
}
/// <summary>
/// Handles the KeyDown event of the textBox control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.Windows.Input.KeyEventArgs"/> instance containing the event data.</param>
private static void textBox_KeyDown(object sender, KeyEventArgs e)
{
// bypass other keys!
if (IsValidOtherKey(e.Key))
{
return;
}
//
TextBoxFilterType filterType = GetFilter((DependencyObject)sender);
TextBox textBox = sender as TextBox;
if (null == textBox)
{
textBox = e.OriginalSource as TextBox;
}
//
switch (filterType)
{
case TextBoxFilterType.PositiveInteger:
e.Handled = !IsValidIntegerKey(textBox, e.Key, e.PlatformKeyCode, false);
break;
case TextBoxFilterType.Integer:
e.Handled = !IsValidIntegerKey(textBox, e.Key, e.PlatformKeyCode, true);
break;
ase TextBoxFilterType.PositiveDecimal:
e.Handled = !IsValidDecmialKey(textBox, e.Key, e.PlatformKeyCode, false);
break;
case TextBoxFilterType.Decimal:
e.Handled = !IsValidDecmialKey(textBox, e.Key, e.PlatformKeyCode, true);
break;
case TextBoxFilterType.Alpha:
e.Handled = !IsValidAlphaKey(e.Key);
break;
}
}
/// <summary>
/// Determines whether the specified key is valid other key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>
/// <c>true</c> if [is valid other key] [the specified key]; otherwise, <c>false</c>.
/// </returns>
private static bool IsValidOtherKey(Key key)
{
// allow control keys
if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
{
return true;
}
// allow
// Back, Tab, Enter, Shift, Ctrl, Alt, CapsLock, Escape, PageUp, PageDown
// End, Home, Left, Up, Right, Down, Insert, Delete
// except for space!
// allow all Fx keys
if (
(key < Key.D0 && key != Key.Space)
|| (key > Key.Z && key < Key.NumPad0))
{
return true;
}
// we need to examine all others!
return false;
}
/// <summary>
/// Determines whether the specified key is valid integer key for the specified text box.
/// </summary>
/// <param name="textBox">The text box.</param>
/// <param name="key">The key.</param>
/// <param name="platformKeyCode">The platform key code.</param>
/// <param name="negativeAllowed">if set to <c>true</c> [negative allowed].</param>
/// <returns>
/// <c>true</c> if the specified key is valid integer key for the specified text box; otherwise, <c>false</c>.
/// </returns>
private static bool IsValidIntegerKey(TextBox textBox, Key key, int platformKeyCode, bool negativeAllowed)
{
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
{
return false;
}
if (Key.D0 <= key && key <= Key.D9)
{
return true;
}
if (Key.NumPad0 <= key && key <= Key.NumPad9)
{
return true;
}
if (negativeAllowed && (key == Key.Subtract || (key == Key.Unknown && platformKeyCode == 189)))
{
return 0 == textBox.Text.Length;
}
//
return false;
}
/// <summary>
/// Determines whether the specified key is valid decmial key for the specified text box.
/// </summary>
/// <param name="textBox">The text box.</param>
/// <param name="key">The key.</param>
/// <param name="platformKeyCode">The platform key code.</param>
/// <param name="negativeAllowed">if set to <c>true</c> [negative allowed].</param>
/// <returns>
/// <c>true</c> if the specified key is valid decmial key for the specified text box; otherwise, <c>false</c>.
/// </returns>
private static bool IsValidDecmialKey(TextBox textBox, Key key, int platformKeyCode, bool negativeAllowed)
{
if (IsValidIntegerKey(textBox, key, platformKeyCode, negativeAllowed))
{
return true;
}
if (key == Key.Decimal || (key == Key.Unknown && platformKeyCode == 190))
{
return !textBox.Text.Contains(".");
}
return false;
//
}
/// <summary>
/// Determines whether the specified key is valid alpha key.
/// </summary>
/// <param name="key">The key.</param>
/// <returns>
/// <c>true</c> if the specified key is valid alpha key for the specified text box; otherwise, <c>false</c>.
/// </returns>
private static bool IsValidAlphaKey(Key key)
{
if (Key.A <= key && key <= Key.Z)
{
return true;
}
//
return false;
//
}
}
}
I don’t understand why it behave differently in development environment (debug) and implementation environment (deploy on IIS version 5.1).
p.s: If I remove UpdateSourceTrigger=PropertyChanged in Text properties, it will works fine. But I need that property to update source without losing focus.
Download Source Code here
Thank You
Please change MyHeight property to string instead of double in MyModel class. I have faced similar issue before and solved it this way. Yes you have to do the unnecessary boxing and unboxing between string and double here.But this works.

Numeric Only TextBox

I've looked all over the place, but it seems that examples I have seen allow only numbers 0-9
I'm writing a Pythagorean Theorem program. I wish to have the phone (Windows Phone 7) check if there are ANY alpha (A-Z, a-z), symbols (#,%), or anything other than a number in the textbox. If not, then it will continue computing. I want to check so there will be no future errors.
This is basically a bad pseudocode of what I want it to do
txtOne-->any alpha?--No-->any symbols--No-->continue...
I would actually prefer a command to check if the string is completely a number.
Thanks in advance!
An even better way to ensure that your textbox is a number is to handle the KeyPress event. You can then choose what characters you want to allow. In the following example we disallow all characters that are not digits:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
// If the character is not a digit, don't let it show up in the textbox.
if (!char.IsDigit(e.KeyChar))
e.Handled = true;
}
This ensures that your textbox text is a number because it only allows digits to be entered.
This is something I just came up with to allow decimal values (and apparently the backspace key):
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (char.IsDigit(e.KeyChar))
{
return;
}
if (e.KeyChar == (char)Keys.Back)
{
return;
}
if (e.KeyChar == '.' && !textBox1.Text.Contains('.'))
{
return;
}
e.Handled = true;
}
There are several ways to do this:
You can use TryParse() and check if the return value is not false.
You can use Regex to validate:
Match match = Regex.Match(textBox.Text, #"^\d+$");
if (match.Success) { ... }
// or
if (Regex.IsMatch(textBox.Text, #"^\d+$")) { ... }
Or you can simply only give them the Numeric keyboard. There are several different keyboard layouts you can use. Link
If you want to do more indepth, I have used the KeyDown and KeyUp events to check what was entered and handle the keypress. Link
You can define the textbox's input scope.
Example:
<TextBox InputScope="Digits"></TextBox>
You can use TryParse and see if there is a result.
See http://msdn.microsoft.com/en-us/library/system.int64.tryparse.aspx
Int64 output;
if (!Int64.TryParse(input, out output)
{
ShowErrorMessage();
return
}
Continue..
/// <summary>
/// A numeric-only textbox.
/// </summary>
public class NumericOnlyTextBox : TextBox
{
#region Properties
#region AllowDecimals
/// <summary>
/// Gets or sets a value indicating whether [allow decimals].
/// </summary>
/// <value>
/// <c>true</c> if [allow decimals]; otherwise, <c>false</c>.
/// </value>
public bool AllowDecimals
{
get { return (bool)GetValue(AllowDecimalsProperty); }
set { SetValue(AllowDecimalsProperty, value); }
}
/// <summary>
/// The allow decimals property
/// </summary>
public static readonly DependencyProperty AllowDecimalsProperty =
DependencyProperty.Register("AllowDecimals", typeof(bool),
typeof(NumericOnlyTextBox), new UIPropertyMetadata(false));
#endregion
#region MaxValue
/// <summary>
/// Gets or sets the max value.
/// </summary>
/// <value>
/// The max value.
/// </value>
public double? MaxValue
{
get { return (double?)GetValue(MaxValueProperty); }
set { SetValue(MaxValueProperty, value); }
}
/// <summary>
/// The max value property
/// </summary>
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(double?),
typeof(NumericOnlyTextBox), new UIPropertyMetadata(null));
#endregion
#region MinValue
/// <summary>
/// Gets or sets the min value.
/// </summary>
/// <value>
/// The min value.
/// </value>
public double? MinValue
{
get { return (double?)GetValue(MinValueProperty); }
set { SetValue(MinValueProperty, value); }
}
/// <summary>
/// The min value property
/// </summary>
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(double?),
typeof(NumericOnlyTextBox), new UIPropertyMetadata(null));
#endregion
#endregion
#region Contructors
/// <summary>
/// Initializes a new instance of the <see cref="NumericOnlyTextBox" /> class.
/// </summary>
public NumericOnlyTextBox()
{
this.PreviewTextInput += OnPreviewTextInput;
}
#endregion
#region Methods
/// <summary>
/// Numeric-Only text field.
/// </summary>
/// <param name="text">The text.</param>
/// <returns></returns>
public bool NumericOnlyCheck(string text)
{
// regex that matches disallowed text
var regex = (AllowDecimals) ? new Regex("[^0-9.]+") : new Regex("[^0-9]+");
return !regex.IsMatch(text);
}
#endregion
#region Events
/// <summary>
/// Called when [preview text input].
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The <see cref="TextCompositionEventArgs" /> instance
/// containing the event data.</param>
/// <exception cref="System.NotImplementedException"></exception>
private void OnPreviewTextInput(object sender, TextCompositionEventArgs e)
{
// Check number
if (this.NumericOnlyCheck(e.Text))
{
// Evaluate min value
if (MinValue != null && Convert.ToDouble(this.Text + e.Text) < MinValue)
{
this.Text = MinValue.ToString();
this.SelectionStart = this.Text.Length;
e.Handled = true;
}
// Evaluate max value
if (MaxValue != null && Convert.ToDouble(this.Text + e.Text) > MaxValue)
{
this.Text = MaxValue.ToString();
this.SelectionStart = this.Text.Length;
e.Handled = true;
}
}
else
{
e.Handled = true;
}
}
#endregion
}

Categories