I am displaying a modal dialog when the user double taps inside a TextBlock. Its a backdoor to a hidden settings panel. The TextBlock is contained in a Popup. I am finding that it is always necessary to tap/touch once before any of the buttons in the dialog do anything. Kind of annoying. Initially was using MouseLeftButtonDown and ClickCount==2 on the TextBlock but have also tried the DoubleClickEvent of a Label and their Preview... versions. Nothing I have tried fixes this problem.
<TextBlock Foreground="Black" FontSize="16" Grid.ColumnSpan="4" HorizontalAlignment="Center" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" VerticalAlignment="Center" Padding="0,10,0,10">
<Run Text="{x:Static languages:Strings.SoftwareVersion}"/>
<Run Text="{Binding SoftwareBuild}"/>
<Run Text=" "/>
<Run Text="{x:Static languages:Strings.FirmwareVersion}"/>
<Run Text="{Binding FirmwareBuild}"/>
</TextBlock>
private void TextBlock_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
try
{
if (e.ClickCount == 2)
{
var sw = new SettingsWindow();
sw.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
sw.DataContext = this.DataContext;
sw.ShowDialog();
}
}
catch (Exception ex)
{
ex.HandleException();
}
}
I've made a correction to the title as the problem is only with touch/tap behaviour; the first mouse click does get through only the first touch fails.
Added more code for the SettingsWindow as requested:-
<Window x:Class="XXXXXXX.UserInterface.Views.Miscellaneous.SettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="SettingsWindow" Height="150" Width="200">
<Grid>
<Button Content="Click Me" Click="Button_Click" VerticalAlignment="Center" HorizontalAlignment="Center" Height="48" Margin="50,30,37,41" Width="105" />
</Grid>
</Window>
public partial class SettingsWindow : Window
{
public SettingsWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).Background = new SolidColorBrush(Colors.Red);
(sender as Button).Content = "WAS CLICKED";
}
}
Ive tried focus setting in the load and activate event of the dialog to no avail. Even tried raising a MouseClick event using RaiseEvent.
Same problem if I only count 1 click too but with 1 click the problem goes away if I count MouseButtonUp events not MouseButtonDown, but then I lose the ClickCount==2 option which doesnt work at all. Somewhere a MouseButtonUp event is getting lost.
So I'm about to manage my own double clicking to get this to work ...
but suggestions welcome as to why this breaks.
Jerry
Related
I have a small pop up window coming up when user selects a record from the main grid. I would like to keep this window open after user has made the selection until he or she clicks cancel. Here is my little code. If I comment out this.close() method then control never returns back to execute rest of the code.
private void ClickSubmit(object sender, RoutedEventArgs e)
{
try
{
IsCancelled = false;
// Figure out to keep this little window open after clicking submit !!
this.Close();
return;
}
catch (Exception ex)
{
ex.ToString();
}
}
private void ClickCancel(object sender, RoutedEventArgs e)
{
try
{
Trace.WriteLine("Popup exit !");
IsCancelled = true;
this.Close();
return;
}
catch (Exception ex)
{
ex.ToString();
}
}
OrdRec or = lvOrders.SelectedItem as OrdRec;
PxQtyPopup pop = new PxQtyPopup(or);
//pop.ShowDialog();
pop.Show();
if (!pop.IsCancelled) // check whether price/qty change submitted or popup window was cancelled
(DCtxt as OrdViewModel).ModifyOrder(or, int.Parse(pop.Qty), decimal.Parse(pop.Px));
Bind the IsOpen to a suitable boolean which will instead open or close the popup. The below example uses a ToggleButton's OpenState (boolean) which will open/close the popup.
<ToggleButton Height="30" Width="60"
x:Name="OpenState">
<StackPanel>
<TextBlock Text="{Binding IsChecked, ElementName=OpenState}"
FontSize="18"
VerticalAlignment="Center"
HorizontalAlignment="Center">
</TextBlock>
<Popup Name="myPopup"
IsOpen="{Binding IsChecked, ElementName=OpenState}">
<TextBlock Name="myPopupText"
Background="LightBlue"
Foreground="Blue">Popup Text</TextBlock>
</Popup>
</StackPanel>
</ToggleButton>
Is your Popup a new WPF window? - You answered yes.
One way to do this would be to expose 2 events in your Popup window. ExitWithClose & ExitWithoutClose. Main window can handle these 2 events and do the after popup processing in the handlers.
Otherwise, prefer using WPF Popup control.
WPF Popup works with IsOpen property. Here's how to keep a popup open or close it.
You will see
Xaml:
<Grid Name="MainGrid">
<Button Height="20" Width="100" Click="Button_Click">Click Me!</Button>
<Popup Margin="10,10,0,13" Name="Popup1" HorizontalAlignment="Center" VerticalAlignment="Center"
PlacementTarget="{Binding MainGrid}" Placement="Center"
Width="194" Height="200">
<StackPanel Orientation="Vertical" Background="Gray">
<Button Height="20" Width="150" Click="Button_ClickToStayOpen" Margin="10">Don't Close Me!</Button>
<Button Height="20" Width="150" Click="Button_ClickToClose" Margin="10">Close Me!</Button>
</StackPanel>
</Popup>
</Grid>
Code behind:
private void Button_Click(object sender, RoutedEventArgs e)
{
//Show Popup
Popup1.IsOpen = true;
}
private void Button_ClickToStayOpen(object sender, RoutedEventArgs e)
{
// Do actions
//Keep Popup Open
}
private void Button_ClickToClose(object sender, RoutedEventArgs e)
{
//Close Popup
Popup1.IsOpen = false;
}
When the window opens there will be a Click Me button. When you click it, a popup will launch. Popup will have 2 buttons. One will help you do some action without closing popup. The other will close the popup.
I am trying to practice c# by reproduce an App that is in the Apple AppStore.
In the app, there is a rectangle with the text: "Touch me". When you touch it, the rectangle repositions itself.
After you do this a few times, the text changes to "Do not Touch me". In that case you have to Touch outside of the rectangle.
It all went well, up to the point where you have to touch outside the rectangle.
Here is my event handler:
private void Canvas_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
{
if (click == 0)
{
if (rectangle1.IsMouseOver || textBlock1.IsMouseOver)
{
// reposition and stuff
if (clicks == 10)
{
// Change the value of the variable click to 1
click = 1;
textBlock1.Text = "Do Not Click me";
Canvas.SetLeft(textBlock1, 200);
}
}
}
else
{
if (rectangle1.IsMouseOver || textBlock1.IsMouseOver)
{
// Game Over
this.Close();
} else
{
// reposition and stuff
click = 0;
textBlock1.Text = "Click me";
Canvas.SetLeft(textBlock1, 225);
}
}
}
The program works perfectly up to the point where you have to click outside the rectangle.
The program closes when you click on the rectangle but when you click outside it, nothing happens.
Is there any event-handler that can do the task i want?
Here is my xaml
<Window x:Class="ClickMe.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="510" Width="525" ResizeMode="NoResize">
<Canvas Name="canvas" MouseLeftButtonDown="Canvas_MouseLeftButtonDown_1">
<Rectangle Fill="#FFF4F4F5" Name="rectangle1" HorizontalAlignment="Left" Height="38" Stroke="Black" VerticalAlignment="Top" Width="509" Canvas.Left="0" Canvas.Top="63"/>
<Label Name="label1" Content="0" Canvas.Left="57" Canvas.Top="446"/>
<Label Content="Klicks:" Canvas.Left="10" Canvas.Top="446"/>
<TextBlock Name="textBlock1" Canvas.Left="225" TextWrapping="Wrap" Text="Click Me" Canvas.Top="74" Margin="10,0,0,0"/>
</Canvas>
Canvas is a UIElement. This allows the use of the PointerPressed event.
private void Target_PointerMoved(object sender, PointerRoutedEventArgs e)
{
Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(Target);
if (ptrPt.Properties.IsLeftButtonPressed)
{
//do yo thang
}
}
}
You really just need to set the Background of the Canvas, as it only gets mouse input where it has "rendered content". The background could even be transparent:
<Canvas Name="canvas" Background="Transparent"
MouseLeftButtonDown="Canvas_MouseLeftButtonDown_1">
...
</Canvas>
use this instead of Canvas_MouseLeftButtonDown_1 event:
protected override OnMouseDown(MouseButtonEventArgs e)
{
if(e.Changed == MouseButton.Left)
{
// Your logic on mouse down will go here
}
base.OnMouseDown(e);
}
with this you can click anywhere on the canvas and get the event to fire. I hope this helps..
i want to put a TextBox, together with a Label and a SymbolIcon into a Button, so that the whole thing is clickable. at the start you can only see the label and the symbol. By clicking on the button, the label gets hidden and the textBox appears, where you can type some text. By clicking again the label comes up again with the new entered text and the TextBox disappears.
My problem is, that by setting the focus to the TextBox, the button (parent) also seems to get into focus, because everytime you press the spacebar, the Click Event of the button fires. I dont want this to happen, while the TextBox has focus.
XAML
<Button Click="ToggleTopic"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid>
<TextBlock x:Name="textBlockInfoTopic"
Text=""
HorizontalAlignment="Left"
Margin="100,0,100,0"/>
<TextBox x:Name="textBoxTopic"
PlaceholderText="enter Topic..."
HorizontalAlignment="Stretch"
Margin="100,0,100,0"
Visibility="Collapsed"/>
<SymbolIcon x:Name="symbolTopicButton"
Symbol="Add"
HorizontalAlignment="Right"/>
</Grid>
</Button>
C#
private void ToggleTopic(object sender, RoutedEventArgs e)
{
if (textBoxTopic.Visibility == Visibility.Visible)
{
//non edit mode
textBoxTopic.Visibility = Visibility.Collapsed;
textBlockInfoTopic.Visibility = Visibility.Visible;
symbolTopicButton.Symbol = Symbol.Add;
textBlockInfoTopic.Text = textBoxTopic.Text;
}
else
{
//edit mode
textBoxTopic.Visibility = Visibility.Visible;
textBoxTopic.Focus(FocusState.Programmatic);
textBlockInfoTopic.Visibility = Visibility.Collapsed;
symbolTopicButton.Symbol = Symbol.Go;
textBlockInfoTopic.Text = "";
}
}
I only want to prevent the triggering of the event through the spaceBar. The return key should trigger the event.
Thanks for helping me!
D.
From official document,
If a button has keyboard focus, pressing the Enter key or the Space key also raises the Click event. You generally can't handle low-level PointerPressed events on a Button because it has the Click behavior instead.
If you want to prevent SpaceBar from triggering the Click event, you could override OnProcessKeyboardAccelerators method of Button like the following.
public class MyButton : Button
{
protected override void OnProcessKeyboardAccelerators(ProcessKeyboardAcceleratorEventArgs args)
{
if(args.Key == VirtualKey.Space)
{
args.Handled = true;
}
base.OnProcessKeyboardAccelerators(args);
}
}
Usage
<local:MyButton Click="ToggleTopic"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid IsTapEnabled="False" >
<TextBlock x:Name="textBlockInfoTopic"
Text=""
HorizontalAlignment="Left"
Margin="100,0,100,0"/>
<TextBox x:Name="textBoxTopic"
PlaceholderText="enter Topic..."
HorizontalAlignment="Stretch"
Margin="100,0,100,0"
Visibility="Collapsed"/>
<SymbolIcon x:Name="symbolTopicButton"
Symbol="Add"
HorizontalAlignment="Right"/>
</Grid>
</local:MyButton>
I'm using a list of textboxes for a registering document in a WP8 app.
The number of textboxes is quite large, so the user has to scroll between them.
To navigate between one field to another, I added two applicationbarIcons, next and previous. Pressing on next will change the focus to the next textbox from list, and scroll the content of the scroll viewer with the height of the textbox (in this case 50).
However, sometimes, when switching the focus to the element bellow, the keyboard covers the text box. (the content doesn't scroll up).
Is there a way to force the textbox to move above the keyboard, even if it is in a scroll view?
<ScrollViewer x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock Text="{Binding Source={StaticResource LocalizedStrings}, Path=LocalizedResources.STRING_CONTACT}" Margin="10,5" FontWeight="SemiBold" Foreground="#878780"></TextBlock>
<StackPanel Margin="10,5" Height="190" Background="#F4F3F4">
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="firstNameTxt" BorderThickness="0" Background="Transparent" InputScope="PersonalFullName"><TextBox>
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="lastNameTxt" BorderThickness="0" Background="Transparent" InputScope="PersonalFullName"></my:DefaultTextBox>
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="MobileTxt" BorderThickness="0" InputScope="Number" Background="Transparent" ></TextBox>
<TextBox LostFocus="firstNameTxt_LostFocus_1" GotFocus="firstNameTxt_GotFocus_1" Margin="0,-7" FontSize="23" x:Name="EmailTxt" BorderThickness="0" Background="Transparent">
</StackPanel>
</ScrollViewer>
Code behind:
void left_Click(object sender, EventArgs e)
{
int index = this.controls.IndexOf(currentControl) - 1;
if (index == -1)
{
this.Focus();
return;
}
currentControl = this.controls[index];
ContentPanel.ScrollToVerticalOffset(ContentPanel.VerticalOffset - 50);
currentControl.Focus();
}
This is a common issue on WP8. When a textbox is focused, it will translate Application 's RootVisual to bring it into view. This doesn't work well in some cases (when clipboard is on, or in your case). A workaround is manually translating RootVisual to a desired vertical offset on GotFocus and LostFocus events of TextBox.
private void TranslateRootVisualY(int yNew)
{
var rootFrame = Application.Current.RootVisual as PhoneApplicationFrame;
rootFrame.RenderTransform = new CompositeTransform() {TranslateY = yNew};
}
In your case, you can eliminate the automatic translation and make ScrollViewer scroll to desired offset in GotFocus event:
private void firstNameTxt_GotFocus_1(object sender, RoutedEventArgs e)
{
TranslateRootVisualY(0);
Dispatcher.BeginInvoke(() =>{
double destOffset;
//...calculate destination offset
ContentPanel.ScrollToVerticalOffset(destOffset);
});
}
destOffset can be calculated from sender and other function like GetRectFromCharacterIndex
Basically, I'm trying to make the canvas listen for a touch input (tap) and will increment the number of taps on screen. It isn't working when I touch the screen on my device. I debugged my code and nothing seems out of the ordinary except that the touch is not detected. I checked ZIndex and the canvas is in front of the screen to be touchable. How do I make it work?
XAML:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" Margin="188,10,187,397"/>
<Button Content="Reset" HorizontalAlignment="Stretch" Margin="-18,535,-18,0" VerticalAlignment="Top" Click="Button_Click"/>
<Canvas ZIndex="0" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeave="Canvas_MouseLeave"/>
</Grid>
C#:
int taps = 0; // create var to detect number of times, user touches the screen
// Constructor
public MainPage()
{
InitializeComponent();
}
// method to register the touch as the finger is placed on the screen
private void Canvas_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Canvas c = sender as Canvas;
counter.Text = "TOUCHED!";
}
//method register the touch as the finger is lifting up from the screen
private void Canvas_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
//Canvas c = sender as Canvas;
taps++;
counter.Text = taps.ToString(); //convert var from int to string
}
//method register the touch as the finger leaves the area of the screen
private void Canvas_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
{
//Canvas c = sender as Canvas;
MessageBox.Show("You left the screen without lifting your finger. That does not count as a tap!", "Caution!", MessageBoxButton.OK);
}
// method to reset the counter to zero when button is pressed and released
private void Button_Click(object sender, RoutedEventArgs e)
{
taps = 0; // reset the count
counter.Text = taps.ToString(); // convert var from int to string
}
I don't know why you want to do it with Canvas - it won't work as you have nothing in this Canvas, so it can't register your click/tap, Canvas is also hard to adjust to screen. I think it can be done simpler way if you want to do it with MouseUp/Down - subscribe directly to Grid containing your elements instead of filling this Grid with additional Canvas:
In XAML:
<Grid x:Name="ContentPanel" Margin="12,0,12,0" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="7*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" VerticalAlignment="Center" Grid.Row="0"/>
<Button Content="Reset" HorizontalAlignment="Stretch" VerticalAlignment="Center" Click="Button_Click" Grid.Row="1"/>
<TextBlock Name="Touched" FontSize="50" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Touched" VerticalAlignment="Center" Visibility="Collapsed" Grid.Row="2"/>
</Grid>
In code behind:
private int taps = 0;
public MainPage()
{
InitializeComponent();
ContentPanel.MouseLeftButtonDown += ContentPanel_MouseLeftButtonDown;
ContentPanel.MouseLeftButtonUp += ContentPanel_MouseLeftButtonUp;
}
private void ContentPanel_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
taps++;
counter.Text = taps.ToString(); //convert var from int to string
Touched.Visibility = Visibility.Collapsed;
}
private void ContentPanel_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
Touched.Visibility = Visibility.Visible;
}
// method to reset the counter to zero when button is pressed and released
private void Button_Click(object sender, RoutedEventArgs e)
{
taps = 0; // reset the count
counter.Text = taps.ToString(); // convert var from int to string
}
As you can see I've subscribed to Grid events (which covers whole screen) - but to make it work I had to set its Background Brush to Transparent, otherwise it will work only if you touch text.
There are many other ways to make your App work, but I hope this will help.
Is there a reason why you don't use the touch-events?
Instead of using MouseLeftButtonDown and MouseLeftButtonUp you should use TouchDown and TouchUp.
Only when you don't handle the touch events or the manipulation events they will be mapped to mouse events. In my experience with touch a single tap also not always gets mapped to MouseLeftButtonDown. As far as I know you could also with mouse events only recoginse one finger. When you want to count more fingers it's necessary to use the TouchDown/TouchUp events.
The problem lies in the overlapping style of the grid
so either make grid rows or define a stackpanel inside the grid, something like this.
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<stackpanel>
<TextBlock Name="counter" FontSize="150" HorizontalAlignment="Center" TextWrapping="Wrap" Text="0" Margin="0,0,0,0"/>
<Canvas ZIndex="0" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp" MouseLeave="Canvas_MouseLeave"/>
<Button Content="Reset" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" Click="Button_Click"/>
</stackpanel>
</Grid>
Try and check now.
You should set your Background property. If you don't want any background set it to Transparent:
<Canvas ZIndex="99" Background="Transparent" Name="Canvas" HorizontalAlignment="Center" Height="535" VerticalAlignment="Top" Width="446" Tapped="Canvas_CountMyTaps"/>
(If you want the canvas to be on Top be sure to make it have a greater ZIndex than the other elements that it overlaps)
If not set (the default value is null) the element won't capture any taps/click etc, it will be as if they "fall through".
Also, consider using the Tapped event which is a "higher level" event that will respond to clicks, taps with the finger, stylus, etc.