I have a UserControl which contains a Label and a TextBox. Both are placed inside a stackpanel which is placed in a border.
I now want to receive an Event when the mouse clicks somewere inside the stackpanel or the border. I tried several things, as using transparent Backgrounds, different Events like ismousedirectlyover etc.
Is there a way i can solve this?
You can try by capturing the mousedown event inside your textbox, your label and your stackpanel and bind them all directly to the same method, you will allways get the mousedown event independent on where you clicked.
You can also try to set the
Panel.Zindex
property to a higher number in the stackpanel and then only capture the mousedown event on it.
1) Add an handler for the MouseLeftButtonDown to the border:
<Border MouseLeftButtonDown="Border_MouseLeftButtonDown">
<StackPanel Background="Transparent">
<TextBox x:Name="Text" />
</StackPanel>
</Border>
2) Set the focus manually to the TextBox:
private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Text.Focus();
}
make sure to set the background of the stackpanel to transparent.
Related
I have some StackPanels in a Grid. They are filled with Labels (height of all labels > displayable space). A possible XAML would be:
<Grid>
<StackPanel>
<Label Content="bla" Background="lime" />
<Label ...>
...
</StackPanel>
</Grid>
Every time the size of the Grid changes, I need to change the inner content of the StackPanel. I need to hide the overflowing Label that is only shown partly. To achieve this, I can use following solutions: with a Converter and make a new class that is inherited from StackPanel.
I want to create a different way by using an attached property. I have following code:
//DepProp OverflowVisibility (double), can save height value
public static void Initialized(DependencyObject pObject, DependencyPropertyChangedEventArgs e)
{
var panel = (pObject as Panel) //the StackPanel in this case
panel.SizeChanged += panel_updateInnerLayout;
}
static void panel_LayoutUpdated(object sender, EventArgs e)
{
var parent = sender as Panel;
if(parent != null)
foreach(FrameworkElement element in parent.Children)
{
var elementPos = element.TransformToAncestor(parent).Transform(new Point(0,0));
if(element.ActualHeight + elementPos.Y >
(double)parent.GetValue(OverflowVisibilityProperty))
element.Visibility = Visibility.Hidden;
else
element.Visibility = Visibility.Visible;
}
}
And an example for usage in XAML:
<Grid>
<ItemsControl>
<ItemsPanel>
<ItemsPanelTemplate>
<StackPanel own:OverflowVisibility.OverflowVisibility="{Binding Grid height}" />
</ItemsPanelTemplate>
</ItemsPanel>
</ItemsControl>
</Grid>
Every time the StackPanel changes it's size, I can update my labels with the panel_updateInnerLayout event handler. When the size of StackPanel is changed, everything is working fine.
My Problem: The StackPanel itself doesn't raise SizeChanged because it has a bigger height than the Grid. I need an event that raises every time the Grid changes its height.
My Question: Is there any event instead of SizeChanged, that is called every time I change the Grid size? If not, is there an alternative way with an attached property to solve my problem?
I also tried to set a binding of the height of the StackPanel to ItemsControl ActualHeight but it does not raise the SizeChanged.
Unfortunately, you have chosen the wrong Panel control for your requirements. The StackPanel should only be used when the resizing of its contents is not required, because it doesn't provide any child control resizing abilities. Therefore, you should use a Grid, or any other Panel that provides resizing abilities. Please refer to the Panels Overview page on MSDN for further help with choosing the appropriate Panel.
There are 2 possible events: SizeChanged and LayoutUpdated. SizeChanged doesn't work because the StackPanel is not resized. LayoutUpdated does not work, because the sender of this event is always null and i can not locate what StackPanel was the source.
For more see: Layout Events - SizeChanged and LayoutUpdated.
So there are no possible event available for my approach.
While I searched for a solution, I also found out, that I used the term attached property also for attached behavior and blend behavior. The difference is described here. Summary: properties do nothing with the object but their presence can be used, behaviours change the object behavior. Blend behaviors are behaviors that Microsoft created for Microsoft Blend. The code in my question is attached behavior.
For attached behaviors I didn't found a solution, but for Blend behaviors i found some. You need to add a reference Micosoft.Windows.Interactivity.
After that i used this code:
public class OverflowVisibilityBehavior : Behavior<VirtualizingStackPanel>
{
protected override void OnAttached()
{
AssociatedObject.LayoutUpdated += AssociatedObject_LayoutUpdated;
base.OnAttached();
}
protected override void OnDetaching()
{
AssociatedObject.LayoutUpdated -= AssociatedObject_LayoutUpdated;
}
void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
var parent = AssociatedObject; //that solves the problem: you can get a "sender" information
//...
// Instead of property GetValue
(VisualTreeHelper.GetParent(parent) as ItemsPresenter).ActualHeight
}
}
Some problems left: The parent of the StackPanel must raise SizeChanged. If you put a StackPanel in a StackPanel in a Grid, you need modify it.
Second: LayoutUpdated changes the StackPanel several times. More times than i need.
I have created a button using XAML and have defined some simple properties for it.
<Button Name="btnNext" Grid.Row="1" Content="PARA" Width="200" Grid.Column="1" Background="#FF2D2D2D" HorizontalAlignment="Right" FontSize="40" Height="380" BorderThickness="0" />
It happens that when I click on the button or put the mouse over, it changes color.
I have tried to escape this behaviour in the btnNext_Click method but it does not affect anything.
private void btnNext_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button != null)
{
button.Background = new SolidColorBrush(hexToColorConvertor("#FF2D2D2D"));
START_POINT += (uint)NUMBER_OF_BUTTONS1;
ReadFile(START_POINT);
}
}
Does anyone have any idea how to resolve this?
In XAML, button have default style for different states like Normal, MouseOver, Pressed etc..
Whenever button moves from one state to another, it changes its look using default style obviously. You can find more information related to default style here
Now, If you want to override this default behavior, you can do it easily with Expression-blend. More of this can be found here and here
Hope this information will help you.. :)
My issue is that I have a few controls (buttons, combo-boxes, hit test visible controls, etc) that are on top of a scrollviewer. Now there is no reason for these controls to consume a pointer wheel changed event, and in checking so they do not. But it seems that when the pointer is over these controls and I attempt to scroll, the scrolling event does not get fired on the scrollviewer (I believe that actual event that is supposed to fire is ViewChanged). Now the buttons and stuff should still handle their regular events, such as PointerPressed, KeyDown, etc. But I want to stop them from consuming the event that would cause the scrollviewer to scroll. Any ideas? Thanks in advance.
This is a quick example of what I'm dealing with:
<Grid>
<ScrollViewer>
<StackPanel>
<!-- Insert any number of things here -->
</StackPanel>
</ScrollViewer>
<Button>Hello World</Button>
</Grid>
Add an event to the controls:
public void UIElement_PointerWheelChanged(object sender, PointerWheelChangedEventArgs e)
{
e.Handled = false;
}
I have a WPF application that I am working on where there is a button that is obscured by a partially opaque rectangle overlay. The button is still visible, but it can not receive any events because they are all caught by the rectangle which is on top of it.
Is there any way to set a pass-through so that the event is received by the next visual item underneath? If not is there some other workaround that could be used in this situation?
Set IsHitTestVisible="false" on the opaque overlay.
You need to set IsHitTestVisible="False" for the control over your button.
This example shows that a button is covered by a border, but the border doesn't get any event since because of the IsHitTestVisible="False" condition of border:
<Grid Background="Yellow">
<Button Click="Button_Click" Width="100" Height="25"/>
<Border Background="Cyan" Opacity="0.4" Width="200" Height="200" IsHitTestVisible="False" />
</Grid>
C# code,
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("iiiiiii");
}
You could add the your own event to the rectangle event (or in the click event of the rectangle it self) and check there if it's with in buttons area
Rectangle.Click += your_click_event;
private void your_click_event(object sender, RoutedEventArgs e)
{
//check if it's coordinates are within the underlining button.
//fire button click event
}
But it would be more convient to set
IsHitTestVisible="False"
Like mentioned in other posts. UIElement.IsHitTestVisible Property
I would recommend to look in to routed events in WPF. Routed events get routed based primarily on the visual tree. Routed events support a RoutingStrategy of Bubble, Tunnel, or Direct.
Understanding Routed Events and Commands In WPF
i am trying to set the verticalscrollbar visibility to be visible during a button click event. Why can't i do something like this?
before click event, XAML:
<ScrollViewer VerticalScrollBarVisibility="Hidden" Height="178.75" Width="680" Name="Scroller">
button click event in C#:
Scroller.VerticalScrollBarVisibility = Visibility.Visible;
-.-
It's the wrong enumeration:
Scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
You should really check the types of properties before assigning random stuff to it.