Select anywhere inside Border - c#

I'm trying to create a screen, or border where if the user click anywhere inside within this border. It should turn my border color RED. Currently i have my XAML setup as...
<StackPanel VerticalAlignment="Top" Orientation="Horizontal">
<Border Margin="10" Padding="10" BorderBrush="Blue" BorderThickness="1" MouseDown="OnMouseDown" Width="200" Height="200">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Click anywhere in here, the border should turn red" />
</Border>
<Border Margin="10" Padding="10" BorderBrush="Blue" BorderThickness="1" MouseDown="OnMouseDown" Width="200" Height="200">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Click anywhere in here, the border should turn red" />
</Border>
<Border Margin="10" Padding="10" BorderBrush="Blue" BorderThickness="1" MouseDown="OnMouseDown" Width="200" Height="200">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Click anywhere in here, the border should turn red" />
</Border>
</StackPanel>
And the output looks like this...
The problem now is that the "Border" is unable to recognize my MouseDown button. It doesnt register my mousedown anywhere inside the border, but only on the border itself. I want it so that if the user click anywhere inside, it should change my border color. How can i do that?
Please note that i need to eventually put content inside my border, be it a video, images, multiple UI controls, or whatever, so if user click anything inside this border, it should "select" my border and turn it red.
I experimented with other things like a Rectangle but Rectangle i cannot use because i am unable to put other UI elements or control in there.
Anyone know what is the correct way to do it?
Requirement:
within border selection, turn border red.
within border unselection, turn border back to blue.
border should eventually allow contents inside, such as the textblock, images, video, or anything.

Just add a transparent background to capture mouse clicks
<Border Background="Transparent" Margin="10" Padding="10" BorderBrush="Blue" BorderThickness="1" MouseDown="OnMouseDown" Width="200" Height="200">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Click anywhere in here, the border should turn red" />
</Border>
Note that any controls inside the border could steal events away from the border. In that case you may need a transparent border over the top of everything, or handle routed events. or just use a ToggleButton instead and change its template.

<StackPanel VerticalAlignment="Top" Orientation="Horizontal">
<StackPanel MouseDown="OnMouseDown">
<Border Margin="10" Padding="10" BorderBrush="Blue" BorderThickness="1" Width="200" Height="200">
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap" Text="Click anywhere in here, the border should turn red" />
</Border>
</StackPanel>
Wrap it inside container..

Related

Extra whitespace area at the bottom side of a Popup, it does not resize correctly to fit its content height

In a User Control I have below content:
<Grid>
<Popup x:Name="myPopup"
AllowsTransparency="True"
StaysOpen="False"
PlacementTarget="mouse"
Placement="Bottom">
<Grid>
<Rectangle MinWidth="40" Fill="#fff" Stroke="#BEBEBE"/>
<StackPanel Width="Auto" Height="Auto">
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="Bold"
Foreground="#666666"
Margin="12,15,12,0"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=someText}"
TextWrapping="Wrap"/>
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="SemiBold"
Foreground="#666666"
Margin="12,8,12,10"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=moreText}"
TextWrapping="Wrap" />
<Button x:Name="CloseBtn"
Content="Ok"
Background="White"
BorderBrush="#BEBEBE"
Foreground="Black"
HorizontalAlignment="Right"
Margin="5"
Padding="5"
Click="Close_Click"/>
</StackPanel>
</Grid>
</Popup>
</Grid>
This produces the follwowing window when button is shown:
and this another one when button is not shown:
The button in the window sometimes is visible and sometimes not (making it visible or collapsed respectively), it depends on some conditions. This is make visible or not in code-behind.
When the button is collapsed and not visible, the remaining space at the bottom of the window is removed as expected, the window resizes fine both its height and width according to its content. All works ok. This is just what I want, I mean, the window to be resizable to fit its content without leaving remaining whitespace areas. This is perfect.
Now, instead of a rectangle, I replace it with a path because I want it to be displayed as a speech bubble with an arrow pointing to the target. This path data is created dynamically at run time each time the stackpanel changes its size (I have added a SizeChanged event to the stack panel). See below how it is with this modification (Below code is the same as above but using a path instead of rectangle):
<Grid>
<Popup x:Name="myPopup"
AllowsTransparency="True"
StaysOpen="False"
PlacementTarget="mouse"
Placement="Bottom">
<Grid>
<!-- <Rectangle MinWidth="40" Fill="#fff" Stroke="#BEBEBE"/> -->
<Path x:Name="myPath" Visibility="Hidden"
Fill="White"
Stroke="#BEBEBE"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True">
</Path>
<StackPanel x:Name="stackpanel" Width="Auto" Height="Auto"
SizeChanged="StackPanel_SizeChanged">
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="Bold"
Foreground="#666666"
Margin="12,15,12,0"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=someText}"
TextWrapping="Wrap"/>
<TextBlock FontFamily="Segoe UI"
FontSize="12"
FontWeight="SemiBold"
Foreground="#666666"
Margin="12,8,12,10"
MinWidth="100"
MaxWidth="150"
SnapsToDevicePixels="True"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
Text="{Binding Path=moreText}"
TextWrapping="Wrap" />
<Button x:Name="CloseBtn"
Content="Ok"
Background="White"
BorderBrush="#BEBEBE"
Foreground="Black"
HorizontalAlignment="Right"
Margin="5"
Padding="5"
Click="Close_Click"/>
</StackPanel>
</Grid>
</Popup>
</Grid>
In the StackPanel_SizeChanged event I create a path Data in code-behind that then I associate to the path in the xaml view. The code in the StackPanel_SizeChanged event is the following:
private void StackPanel_SizeChanged(object sender, SizeChangedEventArgs e)
{
double width = e.NewSize.Width;
double height = e.NewSize.Height;
string stringPathData = $"M8,7.41 L15.415,0 L22.83,7.41 L{width},7.41 L{width},{height} L0,{height} L0,7.41 L8,7.41";
TypeConverter converter = TypeDescriptor.GetConverter(typeof(Geometry));
this.myPath.Data = (Geometry)converter.ConvertFrom(stringPathData);
}
Path is drawn correctly around the window. But now the window does not adjust to fit its content. It fits the content width correctly but not the height. A whitespace area is kept at the bottom side of the window even when button is collapsed. See below:
I have observed that the window always keeps the largest height. I mean if I put some large text and after that a shorter text in the window, window maintains the largest height (in this case the first correponding to the large text) so this produces a whitespace are at the bottom side of the window. It looks like that when changing from a larger text to a shorter text the StackPanel_SizeChanged event does not get fired (well in fact it does not fire, I have debugged it). So I get the following independently if button is shown or not:
The close button event Close_Click is the following:
private void Close_Click(object sender, RoutedEventArgs e)
{
if (popup != null)
{
this.CloseBtn.Visibility = Visibility.Collapsed;
myPopup.IsOpen = false;
myPopup.StaysOpen = false;
}
}
I need the window to fit its content height and width.
PS. Please, if you have any doubts or questions or it is not clear for you, let me know before you spent your time reproducing it.
So the problem is, that the Stackpanel doesnt get rezised? In that case reloading the Popup when the text is changed should help.
Otherwise you could rezise the Popup manually which then resizes the Stackpanel (https://social.msdn.microsoft.com/Forums/vstudio/en-US/f98226ae-31d9-47da-a69a-687659378c94/how-to-resize-a-popup-in-wpf?forum=wpf).

WPF - Making a progressbar button and having it properly size

I am trying to make a button in WPF that will show progress but still have its button text visible.
I tried adding a Grid as a child to the button and adding a ProgressBar and Label to the grid, thinking the Grid will fill the button and using VerticalAlignment="Stretch" HorizontalAlignment="Stretch" on the progress bar and label will get me, basically, a clickable progress bar, that can show progress and have a label on top of it. However, I'm having problem with the sizing.
This is my XAML:
<Button Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinWidth="100" MinHeight="25" Margin="3">
<Grid>
<ProgressBar Value="10" Maximum="20" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<Label Content="asd2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
</Grid>
</Button>
This is what I see:
If I change to explicit sizing:
<Button Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinWidth="100" MinHeight="25" Margin="3">
<Grid>
<ProgressBar Value="10" Maximum="20" Width="100" Height="30" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<Label Content="asd2" Width="100" Height="30" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
</Grid>
</Button>
I get this:
Which, visually, is an improvement, but XAML-programatically is worse, since I want the button to resize with the window, if the user can't see it well or something like that. Also, visually - I don't like that little border between the actual button and the start of the progressbar and I've tried setting both "padding" and "margin" to 0, it's not from that.
What I'd like to see - the progress bar taking up ALL the space of the button and the label text staying centered both vertically and horizontally, with respect to the total size of the button.
Put your <Grid> inside of a ControlTemplate and override your <Button.Template>:
<Button Grid.Column="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MinWidth="100" MinHeight="25" Margin="3">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<ProgressBar Value="10" Maximum="20" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
<Label Content="asd2" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
What you were doing before is putting your <Grid> inside of the Button's ContentTemplate, not its Template. The problem with the ContentTemplate is that it has some of the default button's styling, such as the little border you don't like. By moving it to the Button's overall Template, you're saying I don't care about how the default button looks, I want it to look exactly like THIS.
What it can look like:
What it can look like if you resize the window:

How to set Popup panel index that will overlay other controls in WPF?

I have a problem on how to correctly set the Panel.ZIndex of a Popup inside a Grid. The goal is that when I click the Emergency button, a Popup window will display with an image on it and overlay (cover) the buttons (see screenshot below).
I have set the Grid Panel.ZIndex="0"and the Popup to Panel.ZIndex="1" However, the Popup window doesn't overlay the buttons.
This is the XAML implementation.
<StackPanel Background="Black">
<Grid Background="#253341" Panel.ZIndex="0">
<Popup HorizontalOffset="-5" VerticalOffset="0" IsOpen="False"
HorizontalAlignment="Left" VerticalAlignment="Top"
Name="EmergencyPopup" Placement="RelativePoint" AllowsTransparency="True"
PlacementTarget="{Binding ElementName=EmergencyButton}"
Width="1080" Height="1920" Panel.ZIndex="1">
<Border BorderBrush="Black" BorderThickness="2" CornerRadius="2">
<Grid>
<Image Source="{StaticResource EdenParkInfoImg}"/>
<Label FontWeight="Bold" Foreground="Red" HorizontalAlignment="Right" FontSize="25"
MouseLeftButtonDown="Label_MouseLeftButtonDown">close X</Label>
</Grid>
</Border>
</Popup>
</Grid>
</StackPanel>
Screenshot of the Popup window and buttons (the red box indicates that the image inside the Popup is behind the buttons)
Have I correctly set the Panel.ZIndex of the Grid and Popup? What is the correct way of doing it?
Any help is greatly appreciated.
I did find a way on how to solve the issue. In my Popup dialog xaml implementation, I set HorizontalOffset to 0 and VerticalOffset to 180. In that way, Popup dialog vertically overlays the buttons and ZIndex no longer matters. WPFUser is right, it should work without explicitly defining ZIndex.
<Popup HorizontalOffset="0" VerticalOffset="180" IsOpen="False" Width="1080"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Height="1920"
Name="EmergencyPopup" Placement="Top" AllowsTransparency="True">
<Border BorderBrush="Black">
<Grid>
<Image Source="{StaticResource EdenParkInfoImg}" />
<Label FontWeight="Bold" Foreground="Red" HorizontalAlignment="Right" FontSize="25"
MouseLeftButtonDown="Label_MouseLeftButtonDown" Margin="0,0,15,0">close X
</Label>
</Grid>
</Border>
</Popup>

Trying to apply SolidColorBrush resource to HeaderedContentControl BorderBrush

I'd like to link a SolidColorBrush from my Window to Another SolidColorBrush in My dictionary. I didn't find something like this , and may be it's not possible ...
here is the code in my "ResourceDictionary.xaml"
<SolidColorBrush x:Key="BrushBlueTransparent" Color="#33006D8F"/>
And in my windows i want a link to this resource like this :
<SolidColorBrush x:Key="ControlColor" Color="{Binding Source={DynamicResource BrushEvasanOrange}}"/>
For now, this code don't work ...
I want to use this link because i want to use this resource in my page in a multiple "" and if the color had to be change in the futur it could be easy to change with this way.
The Brush resource is used like this:
<HeaderedContentControl
x:Name="_demandeur"
BorderBrush="{DynamicResource BrushEncadre}"
BorderThickness="1"
Padding="10"
Margin="0,20,0,0"
Header="{x:Static p:Resources.EV_Demandeur}"
>
<WrapPanel
Margin="0"
Orientation="Horizontal"
HorizontalAlignment="Left"
>
<TextBlock
TextWrapping="Wrap"
FontWeight="Normal"
Text="text"
/>
</WrapPanel>
</HeaderedContentControl>
It sounds like your problem is that HeaderedContentControl ignores its BorderBrush property. There are two ways to fix this: One is to replace the HeaderedContentControl's Template with one that displays a border around the content, but that's a lot of trouble. Another is to use a subclass of HeaderedContentControl which already has a template that does you want (we'll get to that last).
One very simple option is to simply put a Border around the control, and move the Margin to the Border as well, so the orange border line will be inside the margin. This isn't the right answer in your specific case, but it's a good general answer to "how do I put a border around things in XAML?"
<Border
BorderBrush="{StaticResource BrushEncadre}"
BorderThickness="1"
Margin="0,20,0,0"
>
<HeaderedContentControl
x:Name="_demandeur"
Padding="10"
Header="{x:Static p:Resources.EV_Demandeur}"
>
<WrapPanel
Margin="0"
Orientation="Horizontal"
HorizontalAlignment="Left" >
<TextBlock
TextWrapping="Wrap"
FontWeight="Normal"
Text="text"
/>
</WrapPanel>
</HeaderedContentControl>
</Border>
But I'm wondering if HeaderedContentControl is really what you want here. HeaderedContentControl is a base class for a variety of controls which display content with a header. The subclasses are much more commonly used, and I have a feeling that what you really want here is GroupBox, which is one of those subclasses. You'd use it just the way you were using HeaderedContentControl:
<GroupBox
x:Name="_demandeur"
Padding="10"
Margin="0,20,0,0"
Header="{x:Static p:Resources.EV_Demandeur}"
BorderBrush="{StaticResource BrushEncadre}"
BorderThickness="1"
>
<WrapPanel
Margin="0"
Orientation="Horizontal"
HorizontalAlignment="Left" >
<TextBlock
TextWrapping="Wrap"
FontWeight="Normal"
Text="text"
/>
</WrapPanel>
</GroupBox>

How to make ScrollViewer work only when texblock in it has height greater than ScrollViewer height?

In my ListBox I show different content including text. Text can be long or short. It scrolls by ScrollViewer. Code:
<ScrollViewer MaxHeight="300" VerticalAlignment="Top" Grid.Column="1" Grid.Row="1" >
<TextBlock Style="{StaticResource TextsTextBlock}" Text="{Binding Texts}" Grid.Column="1" Grid.Row="1" />
</ScrollViewer>
and it's also working if text is short, and height of this text do not reach MaxHeight of ScrollViewer. I want to make ScrollViewer works only when text is long and it's height greater than ScrollViewer's MaxHeight, else - it doesn't have to work.
Tried border
<Border BorderBrush="Aqua" BorderThickness="2" MaxHeight="300" VerticalAlignment="Top" Grid.Column="1" Grid.Row="1">
<ScrollViewer VerticalAlignment="Top" VerticalScrollBarVisibility="Auto" >
<TextBlock Style="{StaticResource TextsTextBlock}" Text="{Binding Texts}" Grid.Column="1" Grid.Row="1" />
</ScrollViewer>
</Border>
but it's still scrolls in this border.
Set the VerticalScrollBarVisibility property to Auto.
The default value is Visible which means that the scroll bar is always shown.
By contrast the HorizontalScrollBarVisibility property has a default value of Hidden.
Try removing some of the Grid. properties from the inner controls
<Border BorderBrush="Aqua" BorderThickness="2" MaxHeight="300" VerticalAlignment="Top" Grid.Column="1" Grid.Row="1">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" >
<TextBlock Text="text" TextWrapping="Wrap"/>
</ScrollViewer>
</Border>
this works fine with one line of text
If I copy paste your code it works fine

Categories

Resources