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.
Related
I am trying to make responsive WPF app which shows image. One of the program's functionalities is selecting a piece of an image by clicking and draging the mouse. I use Point p = e.GetPosition((IInputElement)sender); to find cursor position, and I found out I cannot use Stretch="Fill" because it causes the MouseUp cursor to select a little lower than it should and MouseMove is also inaccurate (I have to drag the mouse a lot further than I should). On the internet, I found the reason for this behavior that you cannot use Fill and have to use None instead. However, the image is much smaller without Fill.
This is my XAML:
<Grid Grid.Row = "1"
Grid.Column="1"
HorizontalAlignment="Left"
VerticalAlignment= "Top"
Margin="0,30,0,0">
<Image x:Name= "image1"
Grid.Row = "1"
Grid.Column="1"
Cursor="Cross"
MinWidth="300"
MinHeight="300"
MaxWidth="512"
MaxHeight= "512"
Stretch = "None"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"
VerticalAlignment="Top"
MouseDown="picOriginal_MouseDown"
MouseMove="picOriginal_MouseMove"
MouseUp="picOriginal_MouseUp" />
</Grid>
I don't know how to embed my image so that in the window view it fills the grid without this Fill property and at the same time is responsive for fullscreen. Should I wrap Image with something else from the WPF toolbox?
I find it easier using the background of the picture box to be the image then use the stretch in that. Alternatively, you could use the image with any of the other options, try using the the properties tab, here are the other stretch options tho: None, Fill, Uniform, UniformToFill
Tell me if this helps, tryna get rep, thanks!
I'm having trouble getting the two ListViews to adjust their height to the containing window. I am using a GridSplitter between them. I want one ListView to shrink and one to grow when i drag the GridSplitter.
Here is the stripped down xaml code.
<Grid x:Name="Gridthing">
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition Height="10"/>
<RowDefinition Height="150"/> <!--bottom-->
</Grid.RowDefinitions>
<ListView Name="Things1" Grid.Row="0"/>
<GridSplitter Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightGray"></GridSplitter>
<ListView Name="Things2" Grid.Row="2"/>
</Grid>
However in this example the bottom ListView always 150 tall regardless of what size the window is set too.
Now I can already hear a thousand voices screaming use "*" or "auto" for the the height of the bottom grid row.
However that has a worse problem. The bottom ListView now extends passed the window and has no scroll bar, rendering anything not in the window invisible.
I am looking for a way that allows the two ListViews to take up all the space in the window with a GridSplitter in between and always displays the scroll bar.
Thanks for any help.
The Problem was that my grid was in a userconrol inside a stackpannel inside the main window. I had to swap out the stackpannel for a grid in the main window and then it performed perfectly. thanks dkozl.
I feel like this is something I can do with grids (or maybe a horizontal stack panel), but I'm wondering if there's a simpler way to do this. This is on a Silverlight page, though I assume a solution for WPF will work just as well. At the top I have a label, centered on the page, which shows a current page's title. To the left of this label is a button. Since the label's text can be anything, it, while still centered, can be 400 pixels to 50 pixels wide. Is there a simple way to make the button always be 20 pixels to the left of the label's left hand edge?
The following XAML does it:
<StackPanel>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="Button"
HorizontalAlignment="Right" Margin="0,0,20,0"/>
<Label Grid.Column="1" Content="Some Text in a Label"/>
</Grid>
</StackPanel>
The Grid will reposition the Button whenever the width of the Label changes. No need for a frequently called update method.
You should just be able to call a function to position your button. Call this method after every place you re-size the label.
public void RepositionButton(int horizontalSpacing)
{
int newXPos = lblLabel.Position.X - btnButton.Width - horizontalSpacing;
int newYPos = lblLabel.Position.Y;
btnButton.Position = new Point(newXPos, newYPos);
}
You might want to modify the math of the Y position if it needs to be centered vertically.
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
I have a WPF project where I maintain video ratio, by placing video control inside a ViewBox. The video control is a WinForms object wrapped inside a WindowsFormsHost. I also added a gridSplitter to resize the ViewBox. It all worked great, until I noticed a strange bug. When I would use the gridSplitter control to minimize the ViewBox close to zero, the video ratio would get screwed up after expanding it again. And when I used gridSplitter to contract the ViewBox all the way down to 0, the WindowsFormHost would completely disappear after expanding (it's still there, but it's ActualWidth and ActualHeight are now 0).
Removing the ViewBox control, and just using WindowsFormsHost works fine, but I need the ViewBox to control the aspect ratio. If I can't find a solution, I will have to control the ratio myself as a workaround.
I figured I must be doing something wrong, so I wrote a quick test program that reproduces the problem. I will post a link to the complete program below (it's in C#, VS2008).
In the test program I create a grid with two columns with a gridsplitter that lets you resize them. I then place a ViewBox in the left control and place a WindowsFormsHost inside it. I then host a red _winFormsButton inside the WindowsFormsHost.
The button scales fine, until you completely contract the left column and then expand it again. The button is gone. How do I prevent that from happening, so the button continues to scale after contracting and expanding left column? Thanks.
XAML:
<Window x:Class="DisappearingHost.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" HorizontalAlignment="Left" Name="gridSplitter1" Width="10" VerticalContentAlignment="Center" />
<Viewbox>
<WindowsFormsHost Name="windowsFormsHost1" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Viewbox>
</Grid>
</Window>
Code Behind:
public partial class Window1 : Window
{
System.Windows.Forms.Button _winFormsButton = new System.Windows.Forms.Button();
public Window1()
{
InitializeComponent();
_winFormsButton.Text = "I disappear!";
_winFormsButton.Size = new System.Drawing.Size(50, 50);
_winFormsButton.BackColor = System.Drawing.Color.Red;
windowsFormsHost1.Child = _winFormsButton;
}
}
Sample code output:
Link to test project code (VS2008):
code
Place your grid splitter in Column zero, so you won't have WPF layout fight. Here is the modified code (notice Grid Splitter column, horiz alignment, and view box margin):
<GridSplitter Grid.Column="0" HorizontalAlignment="Right" Name="gridSplitter1" Width="10" VerticalContentAlignment="Center" />
<Viewbox Margin="10">
<WindowsFormsHost Name="windowsFormsHost1" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Viewbox>
You can make the ViewBox margin just on the right to make it look better
I ended up getting rid of the Viewbox, and controlling WidowsFormHost dimensions myself.