Incorrect pixel coordinates - wpf

I am using the following code to get pixel coordinates of the mouse position.
private void canvas_MouseMove(object sender, MouseEventArgs e)
{
startPoint = e.GetPosition(this);
}
However, if the user uses the scroll bar to move down a bit then this code does not work. I get the wrong coordinates and the object does not get drawn under the mouse position. Any ideas what going on here?

What you're doing should (more or less) work. You might have some problem with exactly which MouseMove event you are listening to, though.
Here is a sample app that demonstrates the desired behavior.
The XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Margin="12">
<ScrollViewer Name="scrollViewer"
HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"
MouseMove="ScrollViewer_MouseMove">
<Canvas Name="canvas" Width="800" Height="600" />
</ScrollViewer>
</Grid>
</Window>
The code-behind:
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ScrollViewer_MouseMove(object sender, MouseEventArgs e)
{
Point mousePosition = e.GetPosition(canvas);
var rectangle = new Rectangle
{
RenderTransform = new TranslateTransform(
mousePosition.X,
mousePosition.Y),
Stroke = Brushes.Black,
};
canvas.Children.Add(rectangle);
}
}
}
The key here is I bound the MouseMove event to the ScrollViewer, and checked the position of the Canvas.

Related

WPF Radio Buttons

I am creating Radio button on Visual Studio and I am having a trouble with Binding
This is my button:
<RadioButton VericalAlignment="Center" GroupName="group1" Content="name"></RadioButton>
I want that if the button was selected then the value of {"someString " + Content Value} will be bind
to SomeClass.variable
is something like this possible?
Thank you!
Something like this should work:
XAML:
<Window x:Class="StackOverflowRadioButton.MainWindow"
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"
xmlns:local="clr-namespace:StackOverflowRadioButton"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Margin="81,36,-81,-36">
<RadioButton Content="RadioButton" HorizontalAlignment="Left" Margin="111,135,0,0" VerticalAlignment="Top"
Name="myRadioButton" Checked="myRadioButton_Checked"/>
</Grid>
CS file:
using System.Windows;
namespace StackOverflowRadioButton
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public string someVariable;
public MainWindow()
{
InitializeComponent();
}
private void myRadioButton_Checked(object sender, RoutedEventArgs e)
{
someVariable = "someString " + myRadioButton.IsChecked;
}
}
}

How to programmatically set UserControl to Topmost?

How to programmatically set UserControl to Topmost of pc screen. I have multiple usercontrol in my wpf application, when I resize any usercontrol, I want to show this usercontrol top of the screen.
i want to show this usercontrol top of the screen.
If by that you mean "top of the screen" inside your application, then that is achieved by using Panel's ZIndex attached property.
Xaml :
<Grid x:Name="LayoutRoot">
<UserControl x:Name="TopMostUserControl"
Margin="10,140,106,48"
Panel.ZIndex="1"
Background="Green" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Panel.ZIndex="0"
Background="red" />
</Grid>
C# :
public MainWindow()
{
InitializeComponent();
Panel.SetZIndex(TopMostUserControl, 1);
Panel.SetZIndex(SecondUserControl, 0);
}
<Grid x:Name="LayoutRoot">
<UserControl x:Name="TopMostUserControl"
Margin="10,140,106,48"
Background="Green" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Background="red" />
</Grid>
Result :
However, if you mean to topmost that UserControl on the entire screen, then that would be something different, you should create another Window that hosts your topmost UserControl and you should change its TopMost property to true when you resize your other UserControls.
MainWindow :
<Grid x:Name="LayoutRoot">
<UserControl x:Name="FirstUserControl"
Margin="10,140,106,48"
Background="Green"
MouseDown="FirstUserControl_OnMouseDown" />
<UserControl x:Name="SecondUserControl"
Margin="39,50,37,87"
Background="red" />
</Grid>
Code Behind :
public partial class MainWindow : Window
{
public TopMostWindow TopMostWindow;
public MainWindow()
{
InitializeComponent();
TopMostWindow = new TopMostWindow();
TopMostWindow.Show();
}
private void FirstUserControl_OnSizeChanged(object sender, SizeChangedEventArgs e)
{
TopMostWindow.Topmost = true;
}
private void MainWindow_OnContentRendered(object sender, EventArgs e)
{
FirstUserControl.SizeChanged += FirstUserControl_OnSizeChanged;
SecondUserControl.SizeChanged += FirstUserControl_OnSizeChanged;
}
//This is to simulate the resizing
private void FirstUserControl_OnMouseDown(object sender, MouseButtonEventArgs e)
{
FirstUserControl.Width = 400;
}
}
TopMostWindow :
<Window x:Class="MvvmLight1.TopMostWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TopMostWindow"
Width="300"
Height="300"
Topmost="False"
WindowStyle="None">
<Grid>
<UserControl x:Name="TopMostUserControl" Background="Blue" />
</Grid>
</Window>
It depends in which container you are using it. Or in what scenario. Basically in Grid you just need to specify it as a last element under Grid container. Otherwise use Panel.ZIndex="1" on the UserControl declaration in XAML

Keep focus on another control while selecting items in a ListBox

I have TextBox which should always be in focus.
At the same time I have as list box.
When user clicks on certain item in this listobox the item clicked gets focus.
I tried to set Focusable="false" for each ListBoxItem in my ListBox but in this case no item can be selected.
I found following code using dotPeek:
private void HandleMouseButtonDown(MouseButton mouseButton)
{
if (!Selector.UiGetIsSelectable((DependencyObject) this) || !this.Focus())
return;
...
}
Is there any way to solve my problem?
You could handle PreviewMouseDown on the ListBoxItems and mark the event as Handled which will stop the focus being transferred.
You can set e.Handled = true because MouseButtonEventArgs is a RoutedEventArgs.
This demo works to keep focus on the TextBox:
XAML
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Height="350"
Width="525">
<StackPanel FocusManager.FocusedElement="{Binding ElementName=textBox}">
<TextBox x:Name="textBox" />
<ListBox x:Name="listBox">
<ListBoxItem PreviewMouseDown="ListBoxItem_PreviewMouseDown">1</ListBoxItem>
<ListBoxItem PreviewMouseDown="ListBoxItem_PreviewMouseDown">2</ListBoxItem>
<ListBoxItem PreviewMouseDown="ListBoxItem_PreviewMouseDown">3</ListBoxItem>
</ListBox>
</StackPanel>
</Window>
Code Behind
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ListBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
var item = sender as ListBoxItem;
if (item == null) return;
listBox.SelectedItem = item;
e.Handled = true;
}
}
}

How to make PanelDragDropTarget act only as a target and not as a source?

I created a new solution. I added a link to System.Windows.Controls.Toolkit to my Silverlight project and wrote this code:
XAML:
<UserControl x:Class="SilverlightApplication4.MainPage"
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"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid>
<toolkit:PanelDragDropTarget Margin="0,0,150,150" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" AllowedSourceEffects="Copy">
<Grid Name="grid1" Background="Blue">
<Rectangle Height="40" HorizontalAlignment="Left" Margin="5,5,0,0" Name="rectangle1" Stroke="Black" StrokeThickness="1" VerticalAlignment="Top" Width="80" Fill="Red" />
</Grid>
</toolkit:PanelDragDropTarget>
<toolkit:PanelDragDropTarget VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" Margin="150,150,0,0" AllowDrop="True" Drop="PanelDragDropTarget_Drop" AllowedSourceEffects="None">
<Grid Name="grid2" Background="Green" />
</toolkit:PanelDragDropTarget>
</Grid>
</Grid>
</UserControl>
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace SilverlightApplication4
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void PanelDragDropTarget_Drop(object sender, Microsoft.Windows.DragEventArgs e)
{
Rectangle myRectangle = new Rectangle() { Margin = new Thickness(5,5,0,0), Height = 40, Width = 80,
HorizontalAlignment = System.Windows.HorizontalAlignment.Left, VerticalAlignment = System.Windows.VerticalAlignment.Top,
StrokeThickness = 1, Stroke = new SolidColorBrush(Colors.Black), Fill = new SolidColorBrush(Colors.Red)};
grid2.Children.Add(myRectangle);
}
}
}
Now when I drag and drop the small red rectangle from grid1 onto grid2 everything works fine. But when I touch the new added rectangle in grid2 it shows visible signs that it can be dragged. My question is how to make a second PanelDragDropTarget (with grid2 inside) to act only as a target for drag and drop and not as a source? I mean how to block the possibility for a user to drag the new created rectangle in grid2, i.e. to exclude any visible signs that this new rectangle is draggable? Because it's not supposed to be draggable in my case.
I found a solution. For the PanelDragDropTarget adorner of the grid2 I defined an event handler for its ItemDragStarting event.
private void PanelDragDropTarget_ItemDragStarting(object sender, ItemDragEventArgs e)
{
e.Cancel = true;
e.Handled = true;
}
Now when I try to drag elements in grid2 nothing happens (that was my purpose).
Have you tried AllowedSourceEffects="None", works for me in SL5...

wpf - how can I hit test the scrollbars in the scrollviewer?

Can someone please tell me how to hit test the scrollbars of a scrollviewer in WPF?
Thanks,
Andy
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ScrollViewer Name="myScrollViewer" Width="280" Height="200" MouseMove="ScrollViewer_MouseMove" >
</ScrollViewer>
<TextBox Name="myTextBox"></TextBox>
</StackPanel>
</Window>
Code behind ...
using System.Windows.Input;
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1
{
public Window1()
{
InitializeComponent();
}
private void ScrollViewer_MouseMove(object sender, MouseEventArgs e)
{
myTextBox.Text = e.GetPosition(myScrollViewer).X + "," + e.GetPosition(myScrollViewer).Y;
}
}
}
With VisualTreeHelper.HitTest, the MouseEventArgs is relatif to the scrollviewer, so the first parameter is your ScrollViewer.
Then use PointHitTestParameter with the coordinate of the MouseEventArgs.

Resources