Pointer events not triggered on UI Elements in custom control - c#

I am creating an application with a UserControl containing multiple UI Elements. The UserControl is rendered into a StackPanel using ItemsControl since the number of UserControls to be rendered depends on user's input.
The basic XAML in the UserControl is as follows.
<Grid x:Name="Viewport" VerticalAlignment="Top" HorizontalAlignment="Center">
<Border x:Name="ViewportBorder" Background="White" BorderThickness="2, 2, 2, 2" BorderBrush="#FF353334" />
<Image x:Name="Image" Margin="0" UseLayoutRounding="True" ManipulationMode="Scale"/>
<InkCanvas x:Name="InkCanvas" />
<Canvas x:Name="SelectionCanvas" CompositeMode="SourceOver" />
</Grid>
I want to change the cursor icon when user is hovering over the SelectionCanvas (based on a condition check in my case as you might see in the source). It seemed pretty straight forward so I tried to use PointerEntered & PointerExited events to capture & release the pointer from the SelectionCanvas. And PointerMoved to change the cursor icon. But it seems that none of the events were triggering.
I tried binding to the Viewport grid element as well but no luck in that too.
I'm not sure what I missed here. Could someone please help me on this? Any help is much appreciated. Please find the complete source code here.
Please note that a sample PDF is included into the startup project /Resources which you'll have to open from the app.

The PointerEntered and PointerExited events are raised provided that the area that is supposed to raise them is painted so try to set the Background property of the Canvas to some brush like for example Transparent:
<Canvas x:Name="SelectionCanvas" CompositeMode="SourceOver"
Background="Transparent"
PointerEntered="SelectionCanvas_PointerEntered"
...

Related

WPF Button event not firing while Grid have PreviewMouseMove set

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!

WindowsFormsHost child click event

Hey I use the RDPCOMAPILib to shadow screens between two computers.
I added a windows forms user control to my project which include the axRDPViewer.
This Control is added to my WPF View in a windowsFormsHost control and works fine, see code:
<Grid Name="RDP">
<Border BorderBrush="Black" BorderThickness="2">
<WindowsFormsHost MouseDown="host_MouseDown" PreviewMouseDown="host_PreviewMouseDown" x:Name="host">
<controls:RDPViewer Click="viewer_Click" MouseClick="viewer_MouseClick" x:Name="viewer"/>
</WindowsFormsHost>
</Border>
</Grid>
But none of the click events is raised when I click on the control, but I don't know why?
I want to do something when I doubleclick on the control.
Hope somebody knows a solution to my problem.
I don't know anything about the library or control you're using, but you seem to be missing a " in the code you posted. You have
MouseClick="viewer_MouseClick x:Name="viewer"
but it should be
MouseClick="viewer_MouseClick" x:Name="viewer"

Notebook-like background for a TextBox in a Windows Phone App

I am trying to create an application to take notes for windows phone 8.1
I want to give the user,a notebook type of feel.
For this I have created the UI for notes, the XAML is:
<Grid Margin="0,12.333,0,-0.333">
<Grid.Background>
<ImageBrush ImageSource="Images/notebookpaper.jpg"/>
</Grid.Background>
<TextBox TextWrapping="Wrap" Background="{x:Null}" Text="" BorderBrush="{x:Null}" HorizontalAlignment="Left" Margin="60,96,0,0" VerticalAlignment="Top" Height="480" Width="340" BorderThickness="0" GotFocus="TextBox_GotFocus" LostFocus="TextBox_LostFocus" FontFamily="Arial" TextChanged="TextBox_TextChanged" AcceptsReturn="True" FontSize="24.8"/>
<TextBlock Text="Date : " HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Margin="246,10,0,0" Height="20" Width="59"/>
</Grid>
The image notebookpaper.jpg looks like this:
When user types in the text in text box, it looks like:
The problem is that, some characters appear a little above the line, some exactly on the line etc. which looks odd. Also, when I try to scroll, UI appears as:
The text appears striked out, as only the text scrolls and not the background image.
Also I want to be able to provide user a list of 5-6 fonts out of which they can select which one to use for typing the notes.
What should I do, so that the text appears properly aligned and text scrolls properly.
Is there any other way to do this ?
It looks like you have two problems:
Varying line height
Scrolling doesn't match the lines
To solve the first problem, you can probably work with TextBlock.TextLineBounds, talked about a bit in this MSDN blog post and the TextLineBounds enumeration documentation. This only seems to apply to TextBlocks, so you might have to swap between a TextBlock and TextBox as users edit their text.
To solve the second problem, the TextBox styles and templates page has a lot of helpful info. It looks like you can make your ImageBrush the background of your control by overriding TextBoxButtonBackgroundThemeBrush. If that doesn't work when focused, you may have to take the entire template given on the linked page and edit it to put your image in the background (there's a lot of XAML, but you should just be able to put your image in BackgroundElement or just before it).
If it still doesn't scroll, you can try setting ScrollViewer.Background instead; if that doesn't work, you'll need to handle the ScrollViewer.ViewChanging or ScrollViewer.ViewChanged events (probably by overriding it) so that it you can transform the background image by the amount of pixels the scrollviewer has moved.
You can also find the ScrollViewer in your code-behind (and skip dealing with the template) by using VisualTreeHelper. This would allow you to set the background of the ScrollViewer and/or subscribe to its events. This however is more brittle than the other methods and is usually a last resort.

Nullpointer error on event listeners when using StaticResource and MouseDown handler

I have a very odd error case that sprung up the moment I used a StaticResource converter on a Rectangle for coloring its background and at the same time using a MouseDown handler on another component next to it within a DataTemplate. If I narrow the code down a bit, this is what is required to reproduce the error :
In the top I have these resources, one pointing to a converter that takes the boolean from the binding and converts it to a fill background color):
<Window.Resources>
<vm:DesktopViewModel x:Key="DesktopVM" />
<vm:BooleanToColorConverter x:Key="converter" />
</Window.Resources>
And later in the same xaml file I iterate over a list of Alarm objects using this (I have replaced a Grid layout with a StackPanel and removed some other components for shorter code sample, this code snippet below still fails):
<ItemsControl ItemsSource="{Binding Alarms}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<Rectangle Height="20" Stroke="Black" Width="20" RadiusX="4" RadiusY="4" Fill="{Binding Alarm, Converter={StaticResource converter}}"/>
<Image Source="/MyNamespace;component/images/chart.png" Stretch="None" MouseDown="Image_MouseDown" Cursor="Hand"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If I remove the MouseDown handler on the image it runs just fine without the nullpointer error in the start. If I remove the Fill tag in the Rectangle the code works just fine WITH the MouseDown handler!!! (and the handler works just fine too). It seems like the StaticResource reference in Fill is messing up something that makes locating the mouse handler function fail?!?
Note that it fails when the window is created, not while running or clicking anything.
Edit: I had the same nullpointer issue if I replaced the converter with a style using a StaticResource with triggers to do the same as the converter. Its pretty clear that the StaticResource reference in an attribute is the culprit but I have no idea why it should affect the event listener.
Also the order of the compoents dont matter either. If I place the Image before the Rectangle the error is exactly the same.
My guess is that the problem is in your converter code, that it does not take into account that it can get a null value.
Why the effect of the mouseDown? Probably it causes the rendering of the image element at an earlier moment and to request the value of the Fill property at a moment that your ViewModel has not been created yet.
There is too little information to state it with certainty, but converters that do not handle null values properly can be a major pain in WPF development in my experience. A lot of design time instability has had root in converters that did not handle the null values properly.

Focus on Canvas overlapping the listbox in WP7

I have a situation here. I have a page containing a ListBox. The ListBox is populated with Items if it is able to fetch the data from a web service. Now when the user doesn't have network connectivity on his phone or the webservice doesn't respond back with Ok status, I want to show the user a pop-up with an option to Retry or select Ok to stay on the same page (though it sounds dumb). Now for this I used a Canvas:
<Canvas Name="Nonetwork" Height="150" Width="280" HorizontalAlignment="Center" VerticalAlignment="Center" Background="DodgerBlue" Visibility="Collapsed" Margin="111,160,92,160" >
<TextBlock VerticalAlignment="Top" Height="120" Width="280" Text="No Network is currently availabe" TextAlignment="Center" TextWrapping="Wrap" Foreground="White" FontSize="28" />
<Button Margin="30, 80" Height="60" Width="100" Content="OK" FontSize="18" Click="Ok_Click"/>
<Button Margin="150, 80" Height="60" Width="100" Content="Retry" FontSize="18" Click="Retry_Click"/>
</Canvas>
Well as most of you experienced guys would have guessed, the canvas is buried inside the listbox and is not accessible when there is no network connectivity. So I have a blank page with the canvas but the user is not able to click on Ok or Retry. Please help
Please do let me know if there is any other approach to solve this problem. I tried Popup but I cant Navigate to the main page from a pop-up since that is a user control page. Any help is higly appreciated
Well, I placed my Canvas below the ListBox and the problem was solved. I didn't know that positioning of the controls in the XAML would have so much effect ...
The order in which elements are rendered in Silverlight is determined firstly by where they appear in the visual object hierarchy and secondly by their ZIndex property.
The Canvas has a third attached property named ZIndex that you can use to override the default layering of elements. Although this Canvas.ZIndex attached property is defined by the Canvas class, it actually works with any type of panel.
You can also try Canvas.ZIndex property:
Canvas.ZIndex Attached Property
What you do is a wrong practice and not at all recommended.
ChildWindow is the class you should use to display such kind of dialog.
Using a Popup is also another approach you can use.
NOTE: I know the simplest approach would be to use MessageBox.Show(), but it would create a popup out of silverlight frame and does not allow theming/styling and other customizations.

Categories