wpf canvas won't resize - c#

I am trying to learn WPF, but I have reached an impasse. The problem is that I have a control derived from UIControl, relevant parts:
<Grid>
<Border x:Name="OuterBorder" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="2" BorderBrush="Black">
<Canvas x:Name ="InternalCanvas" Width="Auto" Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Ivory">
</Canvas>
</Border>
</Grid>
This gives me a little black dot, when I render the control; I assume this is the border.
I then add code to the constructor after InitizializeComponents:
Label l = new Label();
l.Content = "HELLO";
l.BorderThickness = new Thickness(2);
l.BorderBrush = Brushes.Bisque;
if (this.GetType() == typeof(SO.SOGraphNode))
this.InternalCanvas.Children.Add(l);
The intent of the code is that if the class is not inherited, it should show some kind of placeholder. Which it does.
The problem is that InternalCanvas and it's ecplipsing OuterBorder won't resize around the newly created nice label.
The border remains a dot-border and InternalCanvas' Ivory background is not seen behind the label.
I have googled this alot, beliving that I needed to refresh or update the canvas/control elements, but I'm not so sure anymore. Mainly through watching a lot of Dispatcher.Invoke variations, which I have applied very liberally through out the code at different points, every time with no change in behavior.
WPF is a bit oblique to me still, if anyone knows how I could resolve this problem I do indeed have a shiny "Correct Answer" to dole out. :)
Edit 1 - Screenshot of the results:
Notice the general lack of Ivory background and OuterBorder still remains a small artifact in the topright corner of the control while the childelement is obviously much larger.

Is it important for you that the "InternalCanvas" element is type of canvas?
Because if you use for example a Grid instead, the sample works fine:
<Border x:Name="OuterBorder" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderThickness="2" BorderBrush="Black">
<Grid x:Name ="InternalGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Ivory">
</Grid>
</Border>
edit:
The reason for this behaviour you can read in the remarks section in MSDN:
Canvas is the only panel element that has no inherent layout characteristics. A Canvas has default Height and Width properties of zero, unless it is the child of an element that automatically sizes its child elements. Child elements of a Canvas are never resized, they are just positioned at their designated coordinates. This provides flexibility for situations in which inherent sizing constraints or alignment are not needed or wanted. For cases in which you want child content to be automatically resized and aligned, it is usually best to use a Grid element.

Can you show us how it rendered? I tried your xaml in a new project and I can't figure out what the problem is

Related

How to make use of the ViewBox control to make the application re-sizable?

ViewBox seems to be the go to tool if you want your application to be re-sizable, however, I still cannot get my head around on how to properly use it.
Here's my current code (this approach was recommended by a colleague)
<Window x:Class="WpfApp3.MainWindow"
WindowState="Maximized"
Width="{DynamicResource {x:Static SystemParameters.MaximizedPrimaryScreenWidthKey}}"
Height="{DynamicResource {x:Static SystemParameters.MaximizedPrimaryScreenHeightKey}}">
<Viewbox Stretch="UniformToFill">
<Grid Background="Peru"
Height="1080"
Width="15000">
<Grid Background="Bisque"
HorizontalAlignment="Left"
Width="{DynamicResource {x:Static SystemParameters.MaximizedPrimaryScreenWidthKey}}" >
</Grid>
</Grid>
</Viewbox>
</Window>
The approach is the following:
Wrap everything in a ViewBox with Stretch property set to UniformToFill, such that the aspect ratio of inner-elements in preserved
For the outer most grid, set the Width to some arbitrary huge number and Height to some arbitrary small number
We now have a huge rectangle going off screen to the right, while the height is the height of the window
Create a second grid and horizontally align it the the left
Put all other elements in this grid
Problems
The width of the second grid is set to the width of the primary screen, but because of the ViewBox and its stretch property the width if cut off, so I cannot really use it, as all the elements will be slightly-aligned to the left of the screen
Current layout
Questions
Is this the recommended way of creating dynamic / re-sizable applications in WPF?
Is this the correct way of using the ViewBox control?
How can I fix my problem?
Are there other solutions to using the ViewBox control?
I had this issue when I was trying to make a telerik grid re-sizable. Using a viewbox is the recommended way of creating re-sizable applications in WPF. I've found that using a dock panel is better than margins because it holds the control in place, while the viewbox controls the sizing. You can also add a grid with rows / columns if you need multiple controls. I'm very new to development, so this may not be best practice, however it works for our applications.
<Viewbox Stretch="Fill"
Grid.Row="1"
Grid.Column="1">
<DockPanel Height="300">
<Grid>
*User controls*
</Grid>
</DockPanel>
</Viewbox>

How to vertically center a wingding character in textblock xaml / C# / UWP

I’m trying to use a Wingdings symbol as a graphic in a control and am trying to make it vertically centered within a textbox (UWP app.) I’m putting a visible boarder around it and the fact that the symbol is not vertically centered is noticeable and ruining what I’m going for. If it’s possible it saves me from having to do custom art and the since the Wingdings are resizable my graphic could be somewhat easily rescaled. That's why I don't want to manually adjust the height until it looks centered.
Most the Wingdings aren’t vertically centered but are sometimes used as graphics so I’m wondering if this is doable w/ reasonable effort. A slick xaml way to do this would be ideal but a font metric measuring and then textblock height adjusting tack would be good.
Here’s an example of the problem. The hard drive symbol is not vertically centered in the border.
<Border BorderBrush="Black" BorderThickness="10" Background="White" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock Text=";" FontFamily="Wingdings" FontSize="230"/>
</Border>
EDIT - changed example to declutter and to use Wingdings hard drive symbol because the skull&bones is close enough to vertically centered to confuse the question. The drive symbol is very clearly not vertically centered. My goal to automatically vertically center it even as the font size changes. I can see how XAML may not be able to do this but I'm wondering if some font/text metrics querying exists that I could use to do it.
EDIT 2 - Adding a picture (from above XAML which has the same issues as all the suggested XAML(s):
I'm trying to get the center of the symbol to be at the center of the textblock
The skull & bones is not vertically centered in the border.
Actually by default the skull&bones text should be vertically center. The reason for why your code make it looks not vertically is that the font size is too larger to be inside the border, since Border's height is restricted to 200. So the exceed parts of TextBlock you will not seen which may looks like it is not vertically center.
How to vertically center a wingding character in textblock xaml / C# / UWP
There are several ways to do this, choose which way depend on your prefer.
Remove the height and width properties for the Border control you will see the text vertically center.
<Border BorderBrush="Black" BorderThickness="10" Background="White" HorizontalAlignment="Center">
<TextBlock x:Name="textBlock" Text="N" FontFamily="Wingdings" FontSize="230" />
</Border>
Add a ViewBox control outside the TextBlockcontrol. ViewBox can stretch and scale a single child to fill the available space. This will let your text looks always be center no matter how large is the font size. The text size will depend on the size of Border control. Code as follows:
<Border BorderBrush="Black" BorderThickness="10" Height="200" Width="175" Background="White" >
<Viewbox>
<TextBlock x:Name="textBlock" Text="N" FontFamily="Wingdings" FontSize="230" />
</Viewbox>
</Border>
Just use a TextBox control instead of the component of Border and TextBlock. This will reach the same effects that make the text always center and no matter what is the font size. Pay attention that don't set fixed height and width for the TextBox and also make the TextBox read only. Code as follows:
<TextBox
x:Name="textBox"
HorizontalAlignment="Center"
VerticalAlignment="Center"
BorderBrush="Black"
BorderThickness="10"
FontFamily="Wingdings"
FontSize="230"
IsReadOnly="True"
Text="N"
TextAlignment="Center" />

Setting opacity to the grid changes the opacity of the children controls with each other in windows 8

I have the Grid and I want to set the Opacity 50%. When I set the Opacity of the parent element, some children controls are seen under others. This occurs only in Metro application.
Please tell me how can I apply the Opacity similar to how it works in WPF.
I give a simplified example. In my case, the XAML is much complicated, so the color #80000000 for Grid is not a solution.
I use a multilayer user control. When I set Opacity to it, I see each layer, but layers inside the user control should not be transparent to each other.
<Grid Background="Black"
Opacity="0.5">
<Border Background="Red"
Opacity="1">
<TextBlock Text="Under"
FontSize="100" />
</Border>
<Border Background="Yellow"
Opacity="1">
<TextBlock Text="Over"
FontSize="100" />
</Border>
</Grid>
How it works in Metro: http://i.stack.imgur.com/EM9oJ.png
How it works in WPF (desired): http://i.stack.imgur.com/tRGxi.png
For example, when I set Opacity="0.5" for my book, the pages become also semitransparent: http: //i.stack.imgur.com/SvG0d.png
I think this is the bug in Metro.
Set CacheMode="BitmapCache" on your Grid. This behavior is no longer the default.
The likely reason is that the old behavior needed to render the semi-transparent element to a separate surface requiring more memory and two render passes, while the new default doesn't and should thus be faster, less hardware constrained and still work for many if not most cases.

Make Background Black Except for Single Control

I have this:
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<StackPanel Orientation="Horizontal">
<StackPanel Width="100" Margin="20">
<CheckBox x:Name="cbFoo1" Content="Foo"/>
<TextBlock Text="Foo"/>
<TextBox />
</StackPanel>
<StackPanel Width="100" Margin="20">
<CheckBox x:Name="cbFoo2" Content="Foo"/>
<TextBlock Text="Foo"/>
<TextBox />
</StackPanel>
</StackPanel>
<Rectangle Fill="#BF000000" x:Name="rOverlay"/>
</Grid>
</Window>
I want to make a function foo with argument argControls() that makes rOverlay cover every control in the window except argControls(). Does anyone have any idea how to do this?
What about setting the visibility of the control to Collapsed when you want to hide them.
Option 1 - Draw Order
While a bit of a hack, perhaps the simplest way to accomplish this is to place controls that you wish covered before the rectangle and controls that you wish visible after the rectangle.
One step better (and not a hack) would to use the Panel.ZIndex property instead. This allows you to control the order that the UI elements are drawn regardless of the order that they are defined. This would be accomplished by setting the Panel.ZIndex as follows:
rOverlay to some arbitrary value (like 1)
controls to be covered to something lower than rOverlay (like 0)
controls to be visible to something higher than rOverlay (like 2)
It should however be noted that any transparent regions of your controls will still display the black rectangle behind them. This can either be specifying a background colour or by using another option presented here.
Option 2 - Clipping
Another more complex method involves setting the Clip property of the rectangle to a geometry that only includes the regions that you wish filled. This would likely be accomplished by using an instance of CombinedGeometry class with the CombineMode of Exclude. This would prevent the rectangle from drawing anything over regions outside the clipped region.

XY coordinates of WPF button move on runtime?

I got a pretty weird behavior of my WPF application: the XY position of my button on runtime seems to be divergent to that when I set it in my xaml-Editor of Visual Studio (is there a name for it btw?)
It has no alignments set or panels around it, i have only set it by margins. My button has the following code:
<Button Content="OK" Height="23" Margin="213,319,4,7" Name="button3" Width="75" IsCancel="True" Click="button3_Click" IsEnabled="False" />
Edit:
The margins are fixed because it is a non-resizable dialog. As you can see, the button's slightly moved to the left and up:
xaml-Editor:
Runtime:
Why is that and how can I fix it?
I guess the below link about the Alignment, Margins, and Padding Overview will help you to understand how it is works?
Else place a panel wrappers such as Stackpanel, Wrappand or Grid. It's suitable to work the layout of the controls
EDIT : The problem was with the ResizeMode="NoResize". If you remve this attribute in Window tag, then alignment would be good
Link to Refer
Man, that's the worst way to set the position of a UI element in WPF!
Refactor your XAML to something like this:
<Grid Margin="5">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListView Grid.Row="0" Name="TableList" Margin="5"/>
<Button Grid.Row="1" Name="button3" Content="OK"
Margin="5"
Width="75"
HorizontalAlignment="Right"/>
</Grid>
You see? There is a Grid that handles the position of all its children (in this case, a ListView and a Button).
The Button is put on the second Row, aligned to the right (HorizontalAlignment property).
Both the Grid and its children have Margin=5. This guarantees that the margin of every children is equal respect to the adiacent children and to other controls outside the Grid.
Also, the ListView and the Button are perfectly aligned.
The problem with your approach is that you set the Button Width and its Left Margin and its Right Margin. Maybe the total is not correct because the border of the Window eats some pixel, or simply WPF can't handle all the informations together and misses the calculation, who knows, but the consequence is that you must leave at least one parameter free. In my example, I left free the Margins from the Window. The Margin=5 sets only the relative Margin respect to the other controls, but how much the Button is distant from the left border of the Window is something I leave to the WPF graphical engine to calculate.

Categories