I have XAML:
<Grid MouseMove="onMouseMove" >
<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"
MouseDown="tblButton_MouseDown"
MouseUp="tblButton_MouseUp"
Click="ClickHandlerTableBtn"
TextBlock.TextAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
And code behind:
private void onMouseMove(object sender, MouseEventArgs e)
{
lblCoord.Content = Mouse.GetPosition(Application.Current.MainWindow);
}
On the form there is Label named lblCoord, and there are two buttons that are created after form is loaded.
I want to display mouse coordinate in lblCoord in relation to the Grid, but coords are displayed only when i move mouse cursor over any of the buttons that are placed inside that grid.
My guess is that I am placing MouseMove="onMouseMove" in wrong place.
Thanks for your help.
It will work when you set Background of Grid to anything but Transparent
As default, Grid's background is transparent. When it is transparent, mouse events work when you set Background="Transparent" too.
Mouse events handled nearest parent element with background IMHO
Related
I have a ScrollBar and a ScrollViewer.
I want to scroll the contents of the ScrollViewer using my own ScrollBar.
My problem is that the ScrollBar disappears after a few milliseconds.
This is my code:
<StackPanel HorizontalAlignment="Stretch">
<ScrollBar
x:Name="TestScrollBar"
HorizontalAlignment="Stretch"
Orientation="Horizontal"
Scroll="TestScrollBar_Scroll"
Maximum="{Binding ElementName=TestScrollViewer, Path=ExtentWidth, Mode=OneWay}"
ViewportSize="{Binding ElementName=TestScrollViewer, Path=ViewportWidth, Mode=OneWay}"
Visibility="Visible"
Background="Aqua"/> <!--This is set for seeing when/if the ScrollBar is visible-->
<ScrollViewer
x:Name="TestScrollViewer"
ViewChanged="TestScrollViewer_ViewChanged"
HorizontalAlignment="Stretch"
HorizontalScrollMode="Auto"
HorizontalScrollBarVisibility="Auto"> <!--This is set to Auto for now, but should be Disabled/Hidden later-->
<TextBlock FontSize="144" Text="This is blind text. Ignore this completely. It is only here to fill up the ScrollViewer horizontally."/>
</ScrollViewer>
</StackPanel>
private void TestScrollBar_Scroll(object sender, ScrollEventArgs e)
{
TestScrollViewer.ChangeView(e.NewValue, null, null);
}
private void TestScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
TestScrollBar.Value = TestScrollViewer.HorizontalOffset;
}
When I run my app, the Bar is visible for a few milliseconds (a aqua-colored flash) and disappears after.
I checked all the values that are set in XAML and my code using the Live Visual Tree and Live Property Explorer and everything seems to be fine, but the ScrollBar isn't visible, even when the one of the ScrollViewer is.
How can I fix this?
Even ChatGPT said I should ask on StackOverflow.
You just need to set IndicatorMode to MouseIndicator. The IndicatorMode is None by default.
So, your ScrollBar code should be like this:
<ScrollBar
x:Name="TestScrollBar"
HorizontalAlignment="Stretch"
Background="Aqua"
IndicatorMode="MouseIndicator"
Maximum="{Binding ElementName=TestScrollViewer, Path=ExtentWidth, Mode=OneWay}"
Orientation="Horizontal"
Scroll="TestScrollBar_Scroll"
ViewportSize="{Binding ElementName=TestScrollViewer, Path=ViewportWidth, Mode=OneWay}"
Visibility="Visible" />
If I had any hair left, I would have pulled it out by now. I'm getting better with WPF but I'm still running into odd issues like this one.
EDIT: It has to do with the transparent background between objects in the custom control. On a whim, I set the background on the top stackpanel to black and the control now works; I can move the mouse freely around without losing the buttons. However, I'd really like to have the transparent background in the control...
I've got a usercontrol that consists of 4 buttons, a textblock, and a stand alone image. This is my XAML for the control:
<Border BorderBrush="Transparent" MouseEnter="StackPanel_MouseEnter" MouseLeave="StackPanel_MouseLeave">
<StackPanel Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center">
<StackPanel Orientation="Horizontal" Height="25" VerticalAlignment="Center" HorizontalAlignment="Center" >
<Button Name="btnAdd" HorizontalAlignment="Center" Background="Transparent" HorizontalContentAlignment="Left" ToolTip="Previous" Click="btnAdd_Click"
BorderBrush="Transparent" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source="/Images/add.png" VerticalAlignment="Center" HorizontalAlignment="Center" Name="imgAdd" Width="25" Height="25"></Image>
<TextBlock Background="Transparent" Foreground="AntiqueWhite" VerticalAlignment="Center" Width="25">Add</TextBlock>
</StackPanel>
</Button>
<Button Name="btnEdit" HorizontalAlignment="Center" Background="Transparent" HorizontalContentAlignment="Left" ToolTip="Previous"
Click="btnAdd_Click" BorderBrush="Transparent" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source="/Images/edit.png" VerticalAlignment="Center" HorizontalAlignment="Center" Name="imgEdit" Width="25" Height="25"></Image>
<TextBlock Background="Transparent" Foreground="AntiqueWhite" VerticalAlignment="Center" Width="25">Edit</TextBlock>
</StackPanel>
</Button>
</StackPanel>
<StackPanel Orientation="Horizontal" Height="30" >
<Button Name="btnPrevious" HorizontalAlignment="Left" Background="Transparent" HorizontalContentAlignment="Left" ToolTip="Previous" Click="btnPrevious_Click" BorderBrush="Transparent" >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source="/Images/Previous25px.png" VerticalAlignment="Center" HorizontalAlignment="Center" Name="imgPrevious" Width="25" Height="25"></Image>
</StackPanel>
</Button>
<TextBlock Name="tblkUserType" Background="Transparent" Foreground="AntiqueWhite" HorizontalAlignment="Center" VerticalAlignment="Center" Width="90" >Usertype</TextBlock>
<Button Name="btnNext" HorizontalAlignment="Left" Background="Transparent" HorizontalContentAlignment="Left" ToolTip="Previous" Click="btnNext_Click" BorderBrush="Transparent">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Image Source="/Images/Next25px.png" VerticalAlignment="Center" HorizontalAlignment="Center" Name="imgNext" Width="25" Height="25"></Image>
</StackPanel>
</Button>
</StackPanel>
<Image Source="/Images/Logo50px.png" Height="50" Width="50" ></Image>
</StackPanel>
</Border>
I added in the border to test this out further, previously I had the MouseEnter and MouseLeave events on the top .
The code behind the MouseEnter and MouseLeave are as follows:
private void StackPanel_MouseEnter(object sender, MouseEventArgs e)
{
btnNext.Visibility = Visibility.Visible;
btnPrevious.Visibility = Visibility.Visible;
btnAdd.Visibility = Visibility.Visible;
btnEdit.Visibility = Visibility.Visible;
//Debug.WriteLine("mouseEnter");
}
private void StackPanel_MouseLeave(object sender, MouseEventArgs e)
{
btnNext.Visibility = Visibility.Hidden;
btnPrevious.Visibility = Visibility.Hidden;
btnAdd.Visibility = Visibility.Hidden;
btnEdit.Visibility = Visibility.Hidden;
//Debug.WriteLine("mouseLeave");
}
What is supposed to happen when I hover over the control I want the buttons to pop up / appear.
What happens is that the 4 buttons do appear when I hover over the custom control and when I navigate to the "btnNext" or "btnPrevious" the control stays "open".
If I move my cursor up to "btnAdd" or "btnEdit" about half the way up the buttons disappear because the MouseLeave event is fired. However, all of these objects are under the same stackpanel which contains the MouseEnter and MouseLeave.
I can get to the buttons if I go to btnNext or btnPrevious then move the mouse diagonal to either btnAdd or btnEdit. But I can't go from the tblkUserType straight up.
I was trying to fix an original issue where 1/2 way to the upper buttons and the buttons would flicker on / off. That was "fixed" when I added in height="25" here:
<StackPanel Orientation="Horizontal" Height="25" >
But then I could at least continue up and make it to the buttons but it was painful to watch with all the flickering.
I don't know why this is happening or what to even search on to find anyone with the same issue...
I need to be able to get to the btnAdd and btnEdit from the tblkUserType. I guess I'm assuming incorrectly that everything within the StackPanel (or border) would operate with the MouseEnter and MouseLeave within that coverage but I'm not understanding something.
I found this on SO finally after discovering that transparent backgrounds seem to be affecting the StackPanel. This is what fixed it for me.
WPF Button Background Transparency on Mouse Over
I have this ItemsControl:
<ItemsControl Grid.Row="1" ItemsSource="{Binding Board}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="local:Square">
<Rectangle Stroke="Blue" StrokeThickness="0.5" Width="{Binding Width}" Height="{Binding Height}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
and it simply draws squares onto the screen. I want an event so that when I click on one of the squares it calls that event, I need to also get the object I clicked on (the data type of the template is a Square class and the entire grid is bound to an observable collection called Board), how could I do that?
Put the rectangle in the template of a Button and handle the button's click event. Remember to set the rectangle's Fill to Transparent, or else mouse clicks in the fill area of the button won't be detected.
<Button Click="Rectangle_Click">
<Button.Template>
<ControlTemplate TargetType="Button">
<Rectangle
Fill="Transparent"
Stroke="Blue"
StrokeThickness="0.5"
Width="{Binding Width}"
Height="{Binding Height}"
/>
</ControlTemplate>
</Button.Template>
</Button>
private void Rectangle_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
var square = button.DataContext as Square;
// Do whatever
}
It would be preferable to give Square a command property, and bind Button.Command to that:
public class Square
{
// stuff
public ICommand SelectCommand { get; } // Initialize in constructor
// stuff
}
<Button Command="{Binding SelectCommand}">
<!-- ...as before... -->
But then you need to implement ICommand, etc. The Click event works well enough.
You could also handle MouseLeftButtonDown on the Rectangle itself. You'd still have to set its Fill to Transparent. I prefer this solution because Click behavior is more complicated than MouseLeftButtonDown: For example, when you mouse down on
a button and drag out of the button before releasing the mouse button, Click isn't raised. Users are accustomed to that behavior.
I've got the following piece of XAML code:
<Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,9.5,19,0">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding History}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Tapped="HistoryItemTapped">
<FlyoutBase.AttachedFlyout>
<Flyout>
<StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ScrollViewer>
<TextBlock Foreground="{ThemeResource PhoneMidBrush}" FontSize="{ThemeResource TextStyleExtraLargeFontSize}" HorizontalAlignment="Left" Text="{Binding Expression}" />
</ScrollViewer>
<ScrollViewer>
<TextBlock FontSize="{ThemeResource TextStyleExtraLargePlusFontSize}" HorizontalAlignment="Right" Text="{Binding Result}" />
</ScrollViewer>
</StackPanel>
</Flyout>
</FlyoutBase.AttachedFlyout>
<TextBlock Foreground="{ThemeResource PhoneMidBrush}" FontSize="{ThemeResource TextStyleExtraLargeFontSize}" HorizontalAlignment="Left" Text="{Binding Expression}"
TextTrimming="CharacterEllipsis"/>
<TextBlock FontSize="{ThemeResource TextStyleExtraLargePlusFontSize}" HorizontalAlignment="Right" Text="{Binding Result}"
TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
There are two problems I can't solve:
The flyout is shown upon tapping on one of items:
private void HistoryItemTapped(object sender, TappedRoutedEventArgs e)
{
FlyoutBase.GetAttachedFlyout((FrameworkElement)sender).ShowAt((FrameworkElement)sender);
}
However, no matter how I set up the flyout it always shows on the top of the screen, not over the tapped item. Why?
The flyout contains two TextBlocks on separate ScrollViewers. The text on one of them exceeds width of the flyout, bt the scrollviewer does not appear to be working (I cannot scroll horizontally the textblock). Why is that?
So let's knock these out real quick. Your #1 would be expected result, it's just going off the default FlyoutPlacementMode enumeration wherein generally your flyout is just meant to appear over the top in one of 5 spots, Top, Bottom, Left, Right, or Full(Center)
How to fix it, ditch the flyout control and just animate your own panel to do the same thing on a tap event or whatever, not hard at all.
Your #2, if I remember right the default on ScrollViewerfor something like the HorizontalScrollBarVisibility is False by default. So just add HorizontalScrollBarVisibility="Auto" to it.
Hope this helps, cheers
I am developing a control (Items control) to show boxes in a Room(for example sack).
If the room size is 10 *10 feet then I have to scale it to fit my Screen.
Also all the objects in the room will also need to be scaled.
In my view model I have a collection of these objects(i.e. boxes) with actual dimension.
The ItemPanel of my items control is like a canvas where I can freely move the objects.
currently in my Measure Override or Arrange override of the itemsPanel I get the height and width of the panel. With that height and width I apply the scaling to object while arranging.
So my question is, is the approach better or there is a better alternative.
Regards
Saurabh Dighade
Take a look at this code
<Grid x:Uid="Grid_1" Margin="10" ToolTip="{Binding ToolTip}">
<StackPanel x:Uid="StackPanel_1" Grid.Row="1" Orientation="Horizontal">
<Slider x:Uid="ScaleSlider" x:Name="ScaleSlider" Minimum="0.2" Maximum="5" LargeChange="0.05" SmallChange="0.01"
Value="{Binding ScaleSlider}" IsSnapToTickEnabled="True" TickFrequency="0.1" Visibility="Hidden"/>
</StackPanel>
<ScrollViewer x:Uid="ScrollViewer_1" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border x:Uid="AlStatusBorder" BorderBrush="#101010" BorderThickness="3"
Background="{Binding Color}"
x:Name="AlStatusBorder"
Padding="5"
CornerRadius="10" HorizontalAlignment="Center" VerticalAlignment="Top">
<Grid x:Uid="Grid_2">
<!-- Tachometer Gauge -->
<gauge:CircularGauge x:Uid="gauge:CircularGauge_1" Grid.Row="1" Grid.Column="2" FrameType="CircularTopGradient" Width="150" Height="150" Radius="75" Background="#444444"
RimBrush="#444444">
<gauge:CircularGauge.LayoutTransform >
<ScaleTransform x:Uid="ScaleTransform_1" ScaleX="{Binding ElementName=ScaleSlider, Path=Value}"
ScaleY="{Binding ElementName=ScaleSlider, Path=Value}"/>
</gauge:CircularGauge.LayoutTransform>
</gauge:CircularGauge>
</Grid>
</Border>
</ScrollViewer>
</Grid>
In grid_2 I implement my userControl. When I change a property ScaleSlider, element becomes bigger or smaller, and my usercontrol that is inside also changes it's sizes. May be it is what you are looking for. At least I can move this userControl; change sizes only by changing one property. Note that Im binding ScaleX and ScaleY values