I want to have in my application timepicker, which when pressed long set the current time. Setting the time works correctly (hold event), but it also opens the screen for entering the time (just as when I click on timepicker only). Is it possible to change this behavior? When clicked, I would like to open a screen to set the time as normal, but not when long pressed. Thanks for the reply.
Microsoft.Phone.Controls.TimePicker time = new TimePicker();
time.FontSize = 18;
time.Height = 50;
time.Hold += time_Hold;
private void time_Hold(object sender, System.Windows.Input.GestureEventArgs e)
{
((TimePicker)sender).Value = DateTime.Now;
}
There seems to be no easy way to accomplish this.
You can find the source code of the TimePicker here:
https://phone.codeplex.com/SourceControl/latest#Microsoft.Phone.Controls.Toolkit/DateTimePickers/TimePicker.cs
Maybe subclassing this class and overriding DateTimePickerBase::OnApplyTemplate() could be a way to proceed...
I didn't get the question correctly but as far as I understand that you want to delay the launch. Use DispatcherTimerand wrap the code where you want in the callback.
I think you can disable the click event or override it not to show when clicked.
Related
Long time listener, first time caller here. I'm having a strange issue with the TextBox in WinRT C#/XAML that I hope someone may be able to help me with.
Basically, I'm working on creating a Custom Control that essentially requires a second TextBox to be a copy of the first, including showing the same Text, and showing the same Selected Text. Obviously for the Text requirement I simply respond to the TextChanged event on the first TextBox and set the Text of the second TextBox to the Text from the first, which works great.
For the Selected Text requirement I started with a similar solution, and my code for this is as follows:
void TextBox1_SelectionChanged(object sender, RoutedEventArgs e)
{
this.TextBox2.Select(this.TextBox1.SelectionStart, this.TextBox1.SelectionLength);
}
This seemed to work pretty well when initially used with a mouse:
But I'm having a problem when selecting text with Touch. I double-tap within the TextBox to create the first "anchor" as you do in Touch, then drag to begin the selection; but I only ever manage to select a single character normally before the selection stops. The TextBox doesn't lose focus exactly, but the behaviour is similar to that; the selection anchors disappear and I can't continue selecting anything unless I re-double-tap to start a new selection. If I remove the code to select text in TextBox2 then the Touch selection behaves perfectly in TextBox1.
I've been trying to fix this for a while and cannot, I'm not sure if I can get the desired behaviour with WinRT TextBoxes. Does anyone have any ideas? Or perhaps another way to implement a solution with two TextBoxes with this behaviour?
Thanks a lot.
So this is far from an answer, but discovered a few things that maybe will help you or others come up with a potential workaround. Apologies if these are things you've already seen and noted.
First, it's not the call to TextBox2.Select() that's the problem per se. This for instance, works fine for me
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
TextBox2.Select(3, 5);
}
unfortunately, using start and length versus the hard-coded 3 and 5, that is, the following, DOES NOT WORK:
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
TextBox2.Select(start, length);
}
I also discovered that I could select TWO characters if I started from the end, but only one from the beginning. That got me to thinking about dispatching the call to set the second selection:
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low,
() => TextBox2.Select(start, length));
}
Now I can select 2 from the front and 3 and sometimes 4 from the back. Took it a step further, and was able to select as many as six or seven with a really fast swipe.
private void txt1_SelectionChanged(object sender, RoutedEventArgs e)
{
var start = TextBox1.SelectionStart;
var length = TextBox1.SelectionLength;
Dispatcher.RunIdleAsync((v) => Highlight());
}
public void Highlight()
{
TextBox2.Select(TextBox1.SelectionStart, TextBox1.SelectionLength);
}
Seems like the trick to working around this is not setting TextBox2 until whatever vestiges of the TextBox1 SelectionChanged event have completed.
This may be worth registering on Connect.
Mine is only a partial solution as well.
I did some debugging and noticed that the SelectionChanged event is fired throughout the text selection process. In other words, a single finger "swipe" will generate multiple SelectionChanged events.
As you found out, calling TextBox.Select during a text selection gesture affects the gesture itself. Windows seems to stop the gesture after the programmatic text selection.
My workaround is to delay as long as possible calling the TextBox.Select method. This does work well, except for one edge case. Where this method fails is in the following scenario:
The user begins a select gesture, say selecting x characters. The user, without taking their finger off the screen, pauses for a second or two. The user then attempts to select more characters.
My solution does not handle the last bit in the above paragraph. The touch selection after the pause does not actually select anything because my code will have called the TextBox.Select method.
Here is the actual code. As I mentioned above, there are multiple selection changed events fired during a single selection gesture. My code uses a timer along with a counter to only do the programmatic selection when there are no longer any pending touch generated selection changed events.
int _selectCounter = 0;
const int SELECT_TIMER_LENGTH = 500;
async private void TextBox1_SelectionChanged(object sender, RoutedEventArgs e)
{
// _selectCounter is the number of selection changed events that have fired.
// If you are really paranoid, you will want to make sure that if
// _selectCounter reaches MAX_INT, that you reset it to zero.
int mySelectCount = ++_selectCounter;
// start the timer and wait for it to finish
await Task.Delay(SELECT_TIMER_LENGTH);
// If equal (mySelectCount == _selectCounter),
// this means that NO select change events have fired
// during the delay call above. We only do the
// programmatic selection when this is the case.
// Feel free to adjust SELECT_TIMER_LENGTH to suit your needs.
if (mySelectCount == _selectCounter)
{
this.TextBox2.Select(this.TextBox1.SelectionStart, this.TextBox1.SelectionLength);
}
}
I have a button that launches a time intensive process. When the user hovers over this button a tool-tip is displayed, which is good. However, before this process gets re-routed onto a background thread (10 seconds or so for some stuff to take place) the tool-tip is displayed semi-transparent. I know this is awful coding and it should be put on to a non-UI thread ASAP, but this is the way it is for now...
My question is, how can I get a reference to the buttons tool-tip object so I can make it not visible? I envisage it to look like:
ToolTip someTT = Button.ToolTip; // This only gets or set the tool tip text.
someTT.Active = false;
someTT.Dispose(); // As a last resort.
Sorry guys, I aknowledge that I am a disgusting person for doing this.
Edit: The button is of the ComponantOne RibbonButton-type as part of the Studio for WinForms.
Usually, when you working with the ToolTip, you can find the following code within the Form.InitializeComponent() method:
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.button1 = new System.Windows.Forms.Button();
//...
this.toolTip1.SetToolTip(this.button1, "Tooltip for button1");
Thus you can disable tooltip for the specific button using the same approach:
this.toolTip1.SetToolTip(this.button1, null);
You can also disable a button when the background thread have been started. This also avoids unnecessary the tooltips above this button:
void button1_Click(object sender, EventArgs e) {
toolTip1.Hide(button1);
button1.Enabled = false;
//start the background thread here
}
You have to work with the ToolTip control that you added to your project. Something like ToolTip.Active might work.
From above link:
With the Active property, you can enable or disable the display of
ToolTip text for all controls that have text specified by this
particular ToolTip component. Although more than one ToolTip component
can be created and assigned to a form, setting the Active property to
false only affects the current ToolTip.
If the UI thread is doing work then it won't matter if you find a way to hide the tool tip, it still won't take place until the UI thread is freed up again.
Your solution is what you always knew it would be, move the non-UI processing to a non-UI thread.
I have a user control wherein I would like to do something different in the case of a single click vs. double click. I'm handling mouseLeftButtonDown event as such:
private void cueCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
switch (e.ClickCount)
{
case 1:
{
cueCanvas.Focus();
e.Handled = true;
_mouseStartPoint = Mouse.GetPosition(null);
break;
}
case 2:
{
double pos = Mouse.GetPosition(cueCanvas).X;
TimeSpan time = ConvertFromPosition(pos);
AddNewEvent(time);
e.Handled = true;
break;
}
}
}
The problem is that WPF doesn't really care how many times you've clicked the mouse so I get the first click event even though I'm about to get a second one (in the case of a double-click). Has anyone come up with a way to work around this? I realize I could try to get clever and set some timers such that the first click gets "canceled" in the event that the second one comes in (I realize this is what the framework would be doing anyway). If that's the only answer, does anyone know how we query the system for the appropriate click delay?
To my knowledge, there's really no way to do this. The problem is that you're fighting reality. :-) In reality, there are 2 clicks to a double-click. You want single click to be ignored if quickly followed by a double-click.
You'll have wait a short interval to see if it's followed by a second click. You can query for that interval using the SystemInformation class from WinForms, or just call the Win32 API directly.
Using Windows Forms, .NET 3.5 framework, language: c#
I would like to show a popup window for 1 second to notify users of actions that are performed. For example, when I copy a file X I want to show a notification like "Copied file X to File X-copy". Should be shown for a second, then autohide.
You can use a timer. Something along the lines of the following where ShowFloating does the initial display and HideFloating does, you know.
public void ShowFloatingForXMilliSeconds(int milliSeconds) {
ShowFloating();
if (_autoOffTimer == null) {
_autoOffTimer = new System.Timers.Timer();
_autoOffTimer.Elapsed += OnAutoOffTimerElapsed;
_autoOffTimer.SynchronizingObject = this;
}
_autoOffTimer.Interval = milliSeconds;
_autoOffTimer.Enabled = true;
}
void OnAutoOffTimerElapsed(Object sender, System.Timers.ElapsedEventArgs ea) {
if ((_autoOffTimer != null) && _autoOffTimer.Enabled) {
_autoOffTimer.Enabled = false;
HideFloating();
}
}
Also detach the timer handler and dispose the timer in Dispose.
This topic will help you to make topmost window without stealing focus from currently active window.
To complete your solution, in simple case you need to add a timer on your form to make sure the form auto-closes after 1 second and locate your notification window properly (you probably want it in the bottom right part of the screen? - that's a simple arithmetic exercise).
For more advanced solution, you should create NotificationManager class and manage lifetime of your notification message forms there.
Dispite the answers given. I think a message that pops up is somewhat not user friendly. What about using a statusbar link? It's not that evasive (and you can show the progress)
I am working on a text editor that is based on RichEditBox. I have implemented functionality "Go to line" which eventually resolves to
TextPointer.Paragraph.BringIntoView();
Along with this I also set the caret position.
What I found out is that BringIntoView only works when I click on the RichEditBox first (focus it). Otherwise it seems to get ignored. I can see that the caret position has been adjusted by the code around BringIntoView though.
Does anybody know what is the reason/nature of that problem? How can I overcome it?
Found a workaround for this, not sure if it will work in a pure WPF environment, in my case I'm running WPF inside a mainly Windows Forms solution using WPF UserControls where needed.
Instead of invoking BringIntoFocus() immediately, defer it to a later moment by adding it to a queue that gets handled by a timer. For example:
System.Windows.Forms.Timer DeferredActionTimer = new System.Windows.Forms.Timer() { Interval = 200 };
Queue<Action> DeferredActions = new Queue<Action>();
void DeferredActionTimer_Tick(object sender, EventArgs e) {
while(DeferredActions.Count > 0) {
Action act = DeferredActions.Dequeue();
act();
}
}
In your forms constructor, or in the OnLoad event add:
DeferredActionTimer.Tick += new EventHandler(DeferredActionTimer_Tick);
DeferredActionTimer.Enabled = true;
Finally, instead of calling TextPointer.Paragraph.BringIntoView(); directly, call it like this:
DeferredActions.Enqueue(() => TextPointer.Paragraph.BringIntoView());
Note that the Windows Forms timer kicks events off in the main thread (via the message pump loop). If you have to use another timer you need a bit of extra code. I'd recommend you to use System.Timers.Timer rather than the System.Threading.Timer (it's a little more thread-safe). You would also have to wrap the action in a Dispatcher.Invoke structure. In my case, the WinForms timer works like a charm.
Can't you just give the RichTextBox(?) focus first then, using Keyboard.Focus(richTextBox) or richTextBox.Focus()?