I have a border in MVVM. What I am trying to achieve is to detect mouse left button down outside the border and then hide it. I can do it within the MouseLeftButtonDown event for main window, but I do not know if it is the best solution. How could I do this? I want to avoid this click to interfere with other events, for example, this border is placed in a stackpanel and the stackpanel is being hidden on mouse left button double click.
<Border Grid.Row="2"
x:Name="customPopup"
CornerRadius="10,10,0,0"
Height="25" Margin="0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Width="Auto"
BorderBrush="DarkBlue"
BorderThickness="1"
Background="AntiqueWhite">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center">
<Image Source="/Common.Images;component/Images/Info.png"
Height="20"
Width="20" Stretch="Fill"/>
<TextBlock Margin="5"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Background="Transparent"
FontSize="12">
<Run Text="Click outside to close it"/>
</TextBlock>
</StackPanel>
</Border>
Using MouseDown on the window is probably your best bet to get your desired results. You'll need to do some calculations in order to see if the cursor is outside of the border. Something like:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
// get positions
Point mouseLoc = Mouse.GetPosition(null);
Point borderLoc = customPopup.TranslatePoint(new Point(0,0), null);
// check if the mouse is outside the border
if((mouseLoc.X < borderLoc.x || mouseLoc.X > (borderLoc.X + customPopup.ActualWidth)) && (mouseLoc.Y < borderLoc.Y || mouseLoc.Y > borderloc.Y + customPopup.ActualHeight))
{
// hide the border
}
}
Then to handle the double click, use PreviewMouseDoubleClick. Since Preview events are tunneling rather than bubbling, the double click should get called even if you have a single click event on the same element.
private void Window_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
// double click code...
e.Handled = true;
}
Related
I have a popup for which the size changes dynamically to fit the content. When the size increases, popup width increased in left direction only until it reaches left edge of the window. But in my case, I want popup width to be increased in right direction.
Below is the code snippet I am using
XAML:
<StackPanel>
<TextBox x:Name="popupText" Margin="5"/>
<Button Content="Change PopupText" Click="Button_Click_1" Margin="5"/>
<Canvas x:Name="canvas" Width="200" Height="200" Background="Red">
<Rectangle x:Name="rect" Canvas.Top="50" Canvas.Left="50"
Width="50" Height="100"
Stroke="White" StrokeThickness="3"/>
<Popup x:Name="popup" AllowsTransparency="true"
IsOpen="True" Placement="Relative"
PlacementTarget="{Binding ElementName=canvas}"
PlacementRectangle="50,50,50,100"
HorizontalOffset="0"
>
<TextBlock x:Name="textBlock" FontSize="14" Background="Yellow"
TextWrapping="Wrap" >
This is a popup with a PlacementRectangle.
</TextBlock>
</Popup>
</Canvas>
</StackPanel>
C#:
private void Button_Click_1(object sender, RoutedEventArgs e)
{
this.textBlock.Text += this.popupText.Text;
}
ScreenShots:
Before changing size
After changing size
Type anything in the textbox and click "Change PopupText" button. you can clearly see popup size increasing in left direction.
Is above one behavior of popup? Could I change this behavior and increase popup width in right direction?
Thanks in Advance,
Shobika.
You may want to have a look at custom popup placements.
Set Placement="Custom" on your popup and use the CustomPopupPlacementCallback property to reference a callback. In the callback, you can calculate preferred placements, relative to your placement target.
Is there a way that I can click on a WrapPanel's children and get the children, but without having to insert a Click event in every children? Can I just insert a Click event on the WrapPanel?
my code below:
<ScrollViewer Name="scrollViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Height="500" Margin="1085,154,-89,0" HorizontalAlignment="Left" Width="267" VerticalAlignment="Top">
<WrapPanel Name="Agenda" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="265" Background="#FFEEF4FF">
<Border Name="b06x00" BorderThickness="1" Width="265" BorderBrush="Black" Visibility ="Visible">
<TextBlock TextWrapping="Wrap" Text="06:00" Width="265" Height="15" Background="White"/>
</Border>
...
this Border + TextBlock is repeated 70 times. It's an agenda by the way.
...
</WrapPanel>
</ScrollViewer>
You can handle for example MouseDown event on your WrapPanel as it will bubble up from any control within that panel
<WrapPanel Name="Agenda" ... MouseDown="Agenda_MouseDown">
and in the event handler you can check for OriginalSource like so:
private void Agenda_MouseDown(object sender, MouseButtonEventArgs e)
{
var textBlock = e.OriginalSource as TextBlock;
}
I have a button called test button an when I click on it I want to show a grid whose visbility is set to 0
I created a mouse button event (below) but my Grid (testGrid) is not available in the project.
private void testButton(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
testGrid.Opacity = 1;
}
it highlights testGrid red
new to SL so not sure whats going on here
** EDIT **
xml for the Grid
<Grid x:Name="testGrid" HorizontalAlignment="Left" Width="150" Margin="950,-77,0,0" Height="77" VerticalAlignment="Top" Opacity="0">
</Grid>
<Image x:Name="testButton" HorizontalAlignment="Right" Margin="0,1,180,3" Stretch="Fill" Width="53" Height="49" Cursor="Hand" Opacity="0.8" >
The reason that your grid might not be accessibly in the .cs file is if you have changed the class name in the .cs file, but not in the Xaml directive at the top of your .xaml file.
If these two mis match, visual studio won't be able to link up the two files and so you wouldn't be able to see the grid control in the code behind.
Other items with your code to consider:
Though Opacity will work an alternative I use more often is:
This will show the grid.
testGrid.Visibility = Visibility.Visible;
This will hide the grid.
testGrid.Visibility = Visibility.Collapsed;
Also, Your "Button" is an Image tag and not a button. It is an image with the same name as the method you are trying to call. You will either need to change your Image to allow for an on click event or change it to a button, something like
<Button Click="TestBUtton" Text="MyButton" />
And I'd enter that in the Xaml directly so that when you type in the click event handler it auto generates the method in the code behind for you.
try this:
On XAML
<Grid x:Name="testGrid" HorizontalAlignment="Left" Width="150" Margin="950,-77,0,0" Height="77" VerticalAlignment="Top" Opacity="0">
</Grid>
<Image x:Name="testButton" HorizontalAlignment="Right" Margin="0,1,180,3" Stretch="Fill" Width="53" Height="49" Cursor="Hand" Opacity="0.8" MouseLeftButtonDown="testButton" />
on the cs
private void testButton(object sender, System.Windows.Input.MouseButtonEventArgs e){
testGrid.Visibility = Visibility.Visible;
}
Hi I have the following code, I am drawing a button on a canvas with a button template, when I click on the button I want a message to show up, but it doesn't, even when I register a mouse down event on the button it is still not recognized.
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Button r = e.Source as Button;
if (r != null)
MessageBox.Show(r.ToString());
Point mousePoint = Mouse.GetPosition(mainCanvas);
Button button1 = new Button();
button1.Template = (ControlTemplate)this.FindResource("nodeTemplate");
Canvas.SetTop(button1, mousePoint.Y);
Canvas.SetLeft(button1, mousePoint.X);
mainCanvas.Children.Add(button1);
}
}
<Window.Resources>
<ControlTemplate x:Key="nodeTemplate" TargetType="Button">
<Grid>
<Ellipse x:Name="outerCircle" Fill="Red" Height="50" Width="50"/>
<Ellipse x:Name="innerCircle" Fill="Green" RenderTransformOrigin=".5,.5">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX=".9" ScaleY=".9"/>
</Ellipse.RenderTransform>
</Ellipse>
</Grid>
</ControlTemplate>
</Window.Resources>
<DockPanel>
<Canvas x:Name="mainCanvas" Background="Transparent" MouseLeftButtonDown="Canvas_MouseLeftButtonDown">
</Canvas>
</DockPanel>
The MouseLeftButtonDown is marked as handled by the Button, the event will not reach the canvas, use PreviewMouseLeftButtonDown instead (as they use different routing strategies this event cannot be intercepted by the Button because it is raised on the Canvas first). Alternatively you can attach the event ButtonBase.Click to the Canvas, this of course only registers Button-clicks.
So, my problem is that the MouseLeave event only gets triggered if I move my cursor at a certain speed. Below is a Thumb with a Border. Click the thumb and keep the mouse button down. Move slowly outside the border = no event, Move fast outside the border = event.
<Grid x:Name="LayoutRoot" Background="White">
<Border BorderBrush="Black" BorderThickness="3" Width="200" Height="100"
MouseLeave="Border_MouseLeave">
<Thumb />
</Border>
</Grid>
private void Border_MouseLeave(object sender, MouseEventArgs e)
{
MessageBox.Show("Border_MouseLeave");
}
Is it a bug in silverlight or am I missing something?
Thanx
/Mike
Thanx for the anwers, here's an update:
It seems to have something to do with MouseCapture as Guy suggests. The reason being that I also get the problem using Button or a Rectangle that captures the mouse in code-behind.
If I put a Grid between the Thumb and the Border the problem disappears so I think I will go with that.
I also noticed a related problem as I played around some.
<Grid Width="200" Height="100" Background="Transparent"
MouseLeave="Border_MouseLeave">
<Button />
<Rectangle Width="40" Height="40" Fill="Violet"
HorizontalAlignment="Left" />
</Grid>
If I press the left button and move the cursor to the left over the Rectangle and out the MouseLeave event is not registered.
This is all very strange.