Anchoring a label - c#

I am relatively new to WPF and trying to insert a label computed by an algorithm inside a panel. I create the label in my code. I do not use the designer for the label.
The problem is that when I add the label to the panel, it gets resized when I resize the Window. I want the label to be a fixed height and width. Apparently it is anchored to the bottom of the window (I know that from the usual Winforms behavior).
How can I unanchor it, or give it a fixed size?
EDIT
XAML:
<Window x:Class="TestWrapper.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MyTest" Height="483.833" Width="525" Loaded="Window_Loaded">
<Grid x:Name="MyGrid" Margin="0">
<Grid.Background>
<ImageBrush ImageSource="Resources/Background.jpg" Stretch="Uniform"/>
</Grid.Background>
</Grid>
</Window>
Code:
if (!_initialized)
{
Label lbl = new Label()
{
Content = "Test",
FontSize = 36,
Foreground = new SolidColorBrush(Colors.Red),
Background = new SolidColorBrush(Colors.Black),
HorizontalContentAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = System.Windows.VerticalAlignment.Top
};
this.MyGrid.Children.Add(lbl);
lbl.Margin = new Thickness(0, this.MyGrid.ActualHeight + lbl.ActualHeight, 0, 0);
this._initialized = true;
}

If you simply want to hardcode a width and height, explicitly set the Width and Height attributes of your label:
<Label Width="100" Height="20">Hello World</Label>
A Grid will automatically centre and stretch its children, given no other information, and this is the default behaviour you're likely seeing.
(If you provide more code/markup, I can give a more detailed explanation.)

I suggest to use instead the HorizontalAlignment and VerticalAlignment.
<Label HorizontalAlignment="Center" VerticalAlignment="Center" Content="Hello World" />
In this way, the label is automatically centered and the size is dynamically adapted by the WPF Engine.
Remember also that a WPF interface should not be developed by code behind, in most of cases, if not always. You can easily use the Xaml to resolve your problem.

Related

Changing size of the frame and elements in UWP

I want to know if there is a way to resize the frame and the elements inside of it when the window size change. I always want to have the same proportion in the size of the elements inside the frame.
Example:
1- Windowsize = 100(in x) and Imagesize = 50(in x) locationx = 25
2- Windowsize = 50(in x) and Imagesize = 25(in x) location x = 12.5(~12)
In this case, the windowsize is "something", imagesize is 1/2 of "something" and locationx of the image is 1/4 of something. I wan't to do something like this but with every element inside the frame.
Thanks!
You can use the <ViewBox/> control which does exactly that.
<Page>...
<Grid>
<ViewBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<StackPanel>
<Button Content="test" HorizontalAlignment="Left"/>
<TextBlock Text="some text"/>
</StackPanel>
</ViewBox>
</Grid>
</Page>
In the example below, the ViewBox is placed inside a Grid and stretched both Horizontally and Vertically which causes it to stretch with the Page resize.
Reference docs here.

How to make WrapPanel to show vertical scrollbar when children are full with or without ScrollViewer

I have a WrapPanel and buttons are programmatically created and added as children of the WrapPanel. So, I want to show vertical scrollbar when the WrapPanel is full of buttons (children) to be able to add more buttons continuously.
If we need a scrollbar shown, do we have to bring ScrollViewer? Isn't there a way without ScrollViewer? What I want to get is, because the WrapPanel is of small size, I want a scrollbar to be shown only when needed (like full of children).
My code is simple as below (WrapPanel inside Grid and the Grid is inside TabControl)
Many thanks always for your excellence.
Update: I struggled in finding solution on internet for even several days. And I tried put WrapPanel inside ScrollViewer. However, though I set the VerticalScroll to auto, the vertical scrollbar is always shown even when the WrapPanel doesn't have any children.
Furthermore, when I intentionally make the WrapPanel full of children (buttons), the vertical scrollbar of ScrollViewer doesn't provide scrolldown availability.
And the buttons at the bottom line of WrapPanel shown cut and more, I can't scroll down to see beyond the button at the bottom line. I made buttons to be placed beyond the bottom line of WrapPanel intentionally.
With or without, I want the vertical scrollbar to be shown when only needed (full of children). It seems very easy to be done. But it's difficult to make it work properly.
Solution: was provided by Mr. Henk Holterman
<DropShadowEffect/>
</Button.Effect>
</Button>
<WrapPanel x:Name="WrapPanelGreen" HorizontalAlignment="Left" Height="180" VerticalAlignment="Top" Width="232" UseLayoutRounding="True" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Auto"/>
</Grid>
</TabItem>
</TabControl>
And below is my simple code which make button programmatically and add as a child of WrapPanel.
for (int k = 0; k < Overviews.Length; k++)
{
Button btnoverviewcontent = new Button();
ToolTip tt = new ToolTip();
tt.Content = "Press this button if you want to modify or delete.";
btnoverviewcontent.ToolTip = tt;
btnoverviewcontent.Cursor = Cursors.Hand;
SolidColorBrush mySolidColorBrush = new SolidColorBrush();
mySolidColorBrush.Color = Color.FromArgb(255, 101, 173, 241);
btnoverviewcontent.Background = mySolidColorBrush;
btnoverviewcontent.Effect = new DropShadowEffect
{
Color = new Color { A = 255, R = 0, G = 0, B = 0 },
Direction = 315,
ShadowDepth = 5,
Opacity = 1
};
btnoverviewcontent.Padding = new Thickness(3, 3, 3, 3);
btnoverviewcontent.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
TextBlock textBlock = new TextBlock()
{
Text = Overviews[k],
TextAlignment = TextAlignment.Left,
TextWrapping = TextWrapping.Wrap,
};
btnoverviewcontent.Content = textBlock;
btnoverviewcontent.BorderThickness = new Thickness(0, 0, 0, 0);
btnoverviewcontent.FontStretch = FontStretches.UltraExpanded;
btnoverviewcontent.Margin = new Thickness(5, 5, 5, 5);
WrapPanelGreen.Children.Add(btnoverviewcontent);
btnoverviewcontent.Click += new RoutedEventHandler(OnOverviewClick);
The idea in WPF is that every component has only its own job and if you want certain behavior, you combine multiple components to create the view you are looking for.
This means that in order to get a scroll bar for a panel, you will have to wrap it in a ScrollViewer component. That’s the purpose of the ScrollViewer and that’s the only (sane) solution to solve this.
However, though I set the verticalscroll to auto, the verticalscrollbar is always shown even when the Wrappanel doesn't have any child […]
Then you seem to be using the ScrollViewer incorrectly, or wrapping the wrong element. It should look like this:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<WrapPanel>
<!-- Any number of components here -->
</WrapPanel>
</ScrollViewer>
If I place lots of example labels inside that, then I do get a scroll bar as soon as the window is not large enough to show them all. But if there is enough room, the scroll bar is not displayed.
Note that the ScrollViewer itself needs to have the proper dimensions in the parent element, so make sure that it’s not larger than the visible area. It is also necessary for the WrapPanel (or whatever other element you wrap with the ScrollViewer) to have auto widths and heights. Otherwise, with fixed dimensions, the dimensions of the panel will not change as you modify the panel’s content and as such the scrolling status will not change.
See this complete example with a dynamic number of elements:
<Window x:Class="WpfExampleApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="200">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<WrapPanel Name="panel">
<Button Click="Button_Click">Add child</Button>
</WrapPanel>
</ScrollViewer>
</Window>
Code-behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Label element = new Label() { Content = "This is some example content" };
panel.Children.Add(element);
}
}
...just in case someone is looking at this post after 4.5 years and feels, that the solution doesn't help at all:
I had a similar problem, which was caused by a StackPanel into which my ScrollViewer and dynamic buttons where put in...
Seems like the StackPanel expands the height limitless, so that the ScrollViewer and the WrapPanel always expand their height past the window-bounds. so you couldn't scroll at all. Wrapping that StackPanel into a ScrollViewer helped in my case (although eventually i had to change the controls in the end...)
regards

Draw a centered line on Grid whose width is set automatically?

I have seen several similar questions to this, but no solution works for me, probably because my Grid is set to Stretch . This is the result I am trying to achieve. Basically, I have one Grid and I'd like to draw an X-Axis line( like in the picture at the end of this question).
My XAML
<Grid x:Name="MainGrid" HorizontalAlignment="Stretch" Background="#FF4A70F1">
My CodeBehind
Line XAxis = new Line();
XAxis.Stroke = System.Windows.Media.Brushes.Black;
XAxis.StrokeThickness = 1;
XAxis.X1 = 0;
XAxis.X2 = MainGrid.RenderSize.Width;
XAxis.Y1 = MainGrid.RenderSize.Height / 2;
XAxis.Y2 = MainGrid.RenderSize.Height / 2;
MainGrid.Children.Add(XAxis);
My Problem
I 'd like this line to span the whole window, even if I resize/maximize the window. However, the calculations above for X2,Y1,Y2 don't work( all evaluate to 0, hence NO LINE shown) , whether I use ActualSizeor *RenderSize* . Can someone please point out how to fix that? Thank you
This XAML creates a vertically centered line that stretches horizontally:
<Grid>
<Line HorizontalAlignment="Left" VerticalAlignment="Center" Stroke="Black"
X2="{Binding ActualWidth,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Grid}}"/>
</Grid>

How can I use vector graphics (defined in XAML) as the image of a Ribbon menu item?

I need to convert my WPF application, which has a Ribbon, to use vector graphics for the images on buttons, etc., instead of bitmaps. I've got this working so far, except for the RibbonApplicationMenu items, which use their RibbonApplicationMenu.ImageSource property, with type ImageSource to set the graphic that shows up at the left side of the ribbon menu item.
My vector graphics are defined like this in XAML:
<ControlTemplate xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ViewBox Width="148.854" Height="150.500">
<Canvas Width="148.854" Height="150.500">
<Path>
<!-- . . . yadda yadda yadda . . . -->
</Path>
</Canvas>
<Viewbox>
</ControlTemplate>
These render properly when I set them to be the .Template of a Button, etc.
I can't figure out, however, how to use them for the images that show up in the RibbonApplicationMenu controls. Just setting the .Template property of the RibbonApplicationMenu does not work (it fills the entire control seems to break its functionality).
I attempted to use a VisualBrush and then render it to a RenderTargetBitmap to use as the .ImageSource (I also have to work mostly in code behind for reasons I won't get into):
ContentControl cc = new ContentControl(); // just picked ContentControl as a test
cc.Template = myTemplate; // assume myTemplate has the proper ControlTemplate
VisualBrush visBrush = new VisualBrush();
visBrush.Visual = cc;
// not really sure about the parameters to this next line
RenderTargetBitmap rend =
new RenderTargetBitmap(148.854, 150.5, 120, 96, PixelFormats.Pbgra32);
rend.Render(cc);
RibbonApplicationMenuItem menu = new RibbonApplicationMenuItem();
menu.ImageSource = render;
This compiles, but just shows a blank where the image would go. If I instead use a BitmapImage loaded from an image file as the .ImageSource, it displays correctly.
Any ideas how I can get this to work?
Two things that might need to be done:
Firstly there is no explicit size set for the Canvas in the ControlTemplate, you'll need to assign it a width and height (see the upvoted answer here for details).
The other thing is that you need to Arrange and Measure the Viewbox so that it assumes the required dimensions.
So altering the xaml for the vector graphics to something like:
<ControlTemplate x:Key="Template">
<Viewbox>
<Canvas Height="100" Width="130">
<Path>
<!-- data -->
</Path>
</Canvas>
</Viewbox>
</ControlTemplate>
And the code to:
ControlTemplate controlTemplate =
FindResource("Template") as ControlTemplate;
ContentControl content = new ContentControl();
content.Template = controlTemplate;
// ensure control has dimensions
content.Measure(new Size(200, 200));
content.Arrange(new Rect(0, 0, 200, 200));
RenderTargetBitmap render =
new RenderTargetBitmap((int)content.ActualWidth, (int)content.ActualHeight, 120, 96, PixelFormats.Pbgra32);
render.Render(content);
RibbonApplicationMenuItem menu = new RibbonApplicationMenuItem();
menu.ImageSource = render;
Will hopefully get it working.

WPF databinding problem

I have a grid inside a canvas on a tab.
The grid contains a large bitmap image,
I have(tried to) bound the size of the grid to the size of the tab and also have a five pixel margin around the grid.
imageTab.cs
public ImageTab(SendInfo sendInfo, int numImge, int numAccs)
{
imageDisplay = new ImageDisplay(sendInfo, numImge, numAccs);
imageDisplay.ClipToBounds = true;
CreateCanvas();
}
private void CreateCanvas()
{
Canvas canvas = new Canvas();
canvas.Children.Add(imageDisplay);
this.AddChild(canvas);
}
ImageDisplay.xaml
<UserControl x:Class="MyProj.ImageDisplay">
<Grid Margin="5,5,5,5" Height="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=TabControl, AncestorLevel=1}, Path=ActualHeight}">
<Image/>
</Grid>
</UserControl>
The grid comes off the bottom of the tab area slightly causing the bottom of the image to be cut off.
Is there a problem with my databinding, do I need to apply some sort of offset to it? (size of tab - 10pixels for the margin?)
You don't need to set the Height property at all (also realize that it is incorrect to do so as you have it when you consider the 5 pixel margin, i.e., it would be off by 10 pixels).
Just leave VerticalAlignment and HorizontalAlignment at their default values (which is Stretch) to get the effect you are after here.
Try this on a new Window to see what I mean:
<Window x:Class="WpfApplication9.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="438" Width="587" Background="Pink">
<Grid Background="Black" Margin="5">
</Grid>
</Window>
The grid here will be black and will always stretch to the size of the window, using a 5 pixel margin which you will see because the Window's back color is pink.

Categories

Resources