I have two overlapping grids.
<Grid>
<Grid Name="gridMain" KeyDown="GridMain_KeyDown">
</Grid>
<Grid Name="gridSecond" KeyDown="GridSecond_KeyDown">
</Grid>
</Grid>
Once I'm done with main screen, I disable (make invisible) the main screen and enable (make visible) the second screen. I also have separate KeyDown event handler for each Grid. When the second grid is visible, the GridSecond_KeyDown is never fired. Can someone tell me why? And how to fix it?
Resolved. In retrospect I didn't know enough at the time to ask the right question....
KeyDown event not firing with .NET WinForms?
Related
I have a combobox that is editable and a textbox.
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="86,149,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
<ComboBox x:Name="comboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" Margin="282,150,0,0" IsEditable="True" PreviewMouseDown="ComboBox_PreviewMouseDown"/>
I don't understand why ComboBox_PreviewMouseDown does not trigger, when the focus is on the textbox and I click on the combobox. It just highlights the text in the combobox and sets the focus. Clicking in the combobox when it already has the focus, PreviewMouseDown fires.
Is that what's happening here? Why is a PreviewMouseDown in an unfocused combobox not working?
When ComboBox.IsEditable is set to True, the ComboBox internally sets the focus (and keyboard focus) to the edit TextBox to make it instantly available for text input. This makes total sense as the intention when clicking the edit TextBox is always to enter or edit some text. Otherwise, the user would have to click the TextBox twice to make it receive focus for text input (keyboard focus).
So, to prevent focus stealing, the author marked the MouseDown event as handled i.e. RoutedEventArgs.Handled is set to true. (This is the reason why most non-preview events are marked handled by most controls).
Also, the author wanted to prevent the moving of the caret when clicked into the edit TextBox for the first time (to give it focus): the PreviewMouseDown event's RoutedEventArgs.Handled will only be set to true, if the edit TextBox has no keyboard focus and the drop-down panel is closed. (That's why the second click into the TextBox will pass through to be handled by an added event handler).
To achieve the behavior you expect, you have to handle the UIElement.PreviewGotKeyboardFocus event or the attached Keyboard.PreviewGotKeyboardFocusevent on the ComboBox.
Alternatively register the event handler using the UIElement.AddHandler method and set the handledEventsToo parameter to true:
this.MyComboBox.AddHandler(
UIElement.PreviewMouseDownEvent,
new RoutedEventHandler(MyComboBox_PreviewMouseDown),
true);
I ran into this same issue myself. A simple and effective workaround is to wrap your ComboBox in a lightweight ContentPresenter, then attach your PreviewMouseDown handler to that, like so:
<ContentPresenter x:Name="MyComboBoxWrapper"
PreviewMouseDown="MyComboBoxWrapper_PreviewMouseDown">
<ContentPresenter.Content>
<ComboBox x:Name="MyComboBox" />
</ContentPresenter.Content>
</ContentPresenter>
Additionally, since this control gets the PreviewMouseDown event before the ComboBox does, you not only can use it to pre-process events before the ComboBox even sees them, but you can cut off the ComboBox entirely by setting the event arg's handled property to 'true.'
Works like a charm! No subclassing or other tricks needed and it only requires a lightweight control in the tree!
Notes
As some may have considered, technically you could attach the PreviewMouseDown event to any ancestor of your ComboBox, but you then may have to include logic in that handler to determine if you're actually clicking on the ComboBox vs something else.
By using an explicit ContentPresenter (an incredibly lightweight element that itself doesn't have any rendering logic. It simply hosts other elements), you now have a dedicated PreviewMouseDown handler just for this control. Plus, it makes it more portable should you need to move it around since the two items can travel together.
I have button on the Grid that does not detects PreviewMouseLeftDown click event.
After some testing I figured that the problem is in <Grid PreviewMouseMove="onMouseMove" >
If I remove PreviewMouseMove="onMouseMove" part, then MouseDown event is detected, but i need that line of code, since I also have to detect mouse position inside that grid only.
XAML:
<Grid PreviewMouseMove="onMouseMove" Background="Transparent">
<ItemsControl Name="btnTableImageList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Content}"
Height="{Binding Height}"
Width="{Binding Width}"
Tag="{Binding Tag}"
Margin="{Binding Margin}"
Background="{Binding Background}"
HorizontalAlignment="Center"
PreviewMouseLeftButtonDown ="tblButton_MouseDown"
PreviewMouseLeftButtonUp ="tblButton_MouseUp"
Click="ClickHandlerTableBtn"
TextBlock.TextAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Any idea is welcomed. Thanks!
I totally agree with themightylc, but also understand you... WPF and MVVM are not so "easy" to get used to, I do it for a year more or less, and still have a lot to learn.
In that kind of situation I only could advise you to read some tutorials about WPF, DataBinding and ObservableCollection and ViewModel (these are the keywords you need to know).
1) Create a ViewModel where you can define a ObservableCollection, ObservableCollection is kind of list, but using it you can update your View (almost) automaticaly.so when you launch your application, you will read the list of buttons you need to display, then add them to the ObservableCollection
for your tests will be something like that :
Button button1=new Button();
Button button2=new Button();
//define all dimensions/parameters of your button
MyObservableCollection.Add(button1);
MyObservableCollection.Add(button2);
Then in XAML you just need to specify the ItemsSource of ItemsControls(MyObservableCollection). doing like that you don't need anymore all description of buttons inside.
Then when you click to add a button(in your case), you just need to make in code behind something like
Button newButton=new Button();
newButton.Height=defaultHeight...//width, background etc...
MyObservableCollection.Add(newButton);
again, just for advise if WPF/MVVM is new to you, I would advise to begin with easier samples, make a small listview with simple objects inside, or a listbox.
Could also advise you these websites :
wpf-tutorial.com
www.wpftutorial.net
At the end this is actually working properly.
For test I have set up a label, and in MouseMove event i am sending Mouse Position to that label,lblCoord.Content = Mouse.GetPosition(Application.Current.MainWindow);
In case of MouseClick I am sending lblCoord.Content="MouseClick";
And in case of MouseDown I am sending lblCoord.Content="MouseDown";.
I can see mouse coordinates in lblCoord, I can see MouseClick, but it never displayed MouseDown.
However, if i call MessageBox inside MouseDown event, everything works. So i guess that XAML <Grid> PreviewMouseMove="onMouseMove" works even when I am not moving mouse so it is sending coords to a Label all the time and overwrites lblCoord.Content="MouseDown"; faster than I am able to see it.
The answer to this question is: Don't work with WPF and expect WinForms results...
Thanks to everybody for their time and effort!
I'm having a weird UI issue in my app, where a ScrollViewer jumps to the top as soon as a TextBox child loses focus. I've already tried to set BringIntoViewOnFocusChange="False" in the parent ScrollViewer, but that doesn't solve the issue unfortunately.
Here's a quick video that shows the problem I have:
As you can see, every time the top TextBox is focused, the ScrollViewer jumps back to the top as soon as it loses focus (ie. whenever I tap on an item in the ListViews below. This also happen if I click on one of those ComboBox controls: the ScrollViewer still jumps back immediately.
This is the general structure of the contents of the Popup your're seeing:
<UserControl>
<RelativePanel HorizontalAlignment="Stretch">
<!--Item name-->
<TextBlock Text="Name"/>
<customControls:TextBoxActionButton/>
<customControls:TextValidatorControl/>
<!--Section selector-->
<TextBlock Text="Section"/>
<customControls:ComboBoxWithResetButton/>
<!--Item GroupName-->
<TextBlock Text="Group"/>
<customControls:ComboBoxWithResetButton/>
<!--Template based on-->
<TextBlock Text="Based on"/>
<customControls:ComboBoxWithResetButton/>
<!--Icons list and description-->
<TextBlock Text="Icon"/>
<ListView ScrollViewer.VerticalScrollMode="Disabled"/>
<!--Select color text-->
<TextBlock Text="Select color"/>
<ListView ScrollViewer.VerticalScrollMode="Disabled"/>
</RelativePanel>
</UserControl>
I don't have any code that interacts with the parent ScrollViewer, which is in a completely different UserControl, along with the rest of the Popup UI (header, buttons at the bottom etc..).
I've also tried to subscribe to the LosingFocus event of the first TextBox, and to set e.Handled = true; from there, but that didn't work too.
Do you have any idea on why this is happening? And also, why doesn't the BringIntoViewOnFocusChange="False" property work in this situation?
Thanks!
I think the problem is the TextValidatorControl which causes the TextBox to regain focus, because this does not seem to happen when the control is not there.
Please verify what happens if you actually enter a valid name. If the behavior stops, I would suggest you to invetigate or post the source code of TextValidatorControl, because it looks like the source of the problems.
This is my xaml
<usercontrol xxxxxx
xxxxxxx
<grid >
<Grid.rowdefinition>
<rowdefinition></rowdefinition>
<rowdefinition></rowdefinition>
</Grid.rowdefinition>
<grid Grid.row=2>
<canvas x:name="canvas" Button.click = "Somefunction">
</canvas>
</grid>
</usercontrol>
So I have a User control with 2 rows in a grid, I have a canvas in 2nd row. Well, I am dynamically creating buttons and adding them as a children to the canvas. Now, at present, when any button present in canvas is clicked, this somefunction which i have defined in code behind will be invoked. In somefunction, i have some code which acts according to the button clicked inside the canvas.
Now, What I want is, I want to select 2 buttons, but, selection should happen on long press of the one button followed by long press of the second button. Once, both are selected, I want to execute my own code.
How to code long press button selection on the dynamically created,attached buttons in the canvas explained as above. I found some links in the stackoverflow and codeproject. But, That really didnt gave me proper idea on how to go about with the present xaml and programmed logic. Hence, Please suggest on this, with basis to the above xaml structure and explained logic of program.
Thank you,
Rakesh.N
I think this might help you out...
In my Windows 8 Metro project, I'm using a class derived from ContentControl (let's call it MyControl) to present my content. Inside MyControl I have a ScrollViewer. Because I want my control to handle keyboard events, I need to be able to set the focus to my control. However, I also want the option to let the scrollviewer handle keyevents, such as arrow keys and PageUp/Down. More precisely, I want this to be an option that another programmer can turn on or off. This means that sometimes, I want MyControl to be a tab-stop, and sometimes I want ScrollViewer to be a tab-stop, but never both.
The issue is that I don't want to expose the inner workings of MyControl to other programmers. That is, they ideally should be able to use MyControl.IsTabStop and leave the logic of placing the actual tab-stop with my Control (to put in MyControl or ScrollViewer).
Is there any good way to achieve this, or do I somehow have to work around it by providing a separate function to make my control a tab stop?
If you look at my test XAML you'll see I'm doing nothing, yet the up/down keys in the TextBox work to go between lines of text and they scroll the ScrollViewer when there is no line of text to go to. This is likely achieved by the KeyDown handlers setting the e.Handled value to true when they don't want the key event to bubble up (as when the TextBox already handled it) and leaving it false when the event is not handled, which lets the ScrollViewer handle it. The event will always trigger on the TextBox if it has focus, but it bubbles up the visual tree if it is not handled. It does not seem that you have to do anything more than just deciding whether you want to mark the key events as handled or not.
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer
IsTabStop="True">
<Grid
Width="2000"
Height="2000">
<Button
Margin="149,342,0,311">
<Button>
<TextBox
AcceptsReturn="True"
Height="400"
Width="200"/></Button>
</Button>
</Grid>
</ScrollViewer>
</Grid>