I've designed a grid row as being another grid with a 20/80 split between two columns, with the one on the left having a min width of 250:
<Grid Grid.Row="1" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" MinWidth="250"/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="Red" />
<Grid Grid.Column="1" Background="Blue" />
</Grid>
At widths greater than 1250, this works as expected, but as soon as I shrink below that, the first column stops shrinking (as it should) because it has hit 250, but the second column keeps shrinking at the same rate as it did before (rather than collapsing at the same rate of the surrounding window). The result is that a portion of the content is cut out, even though the grid is set to stretch to its container:
Why isn't the blue frame resizing to fit within its parent container the way other star width columns do? Why has setting a min width broken this all of the sudden?
Update: I've rebuilt my entire UI in a sample window (by simply replacing each section's contents with a border), and am unable to reproduce the issue:
It it possible that the contents (which aren't encountering any MinWidth constraints and seem to be resizing properly as well, albeit too slowly like their parent grid columns) are still somehow impacting the grid columns? What about the fact that the original is in a UserControl and this is in a Window?
I apologize - given the information in the original question, it was impossible to answer this question.
Unfortunately for me the problem is a bug in the implementation of the Xceed DataGridControl. By simply replacing each DataGridControl with a border or other control in my original UI, all elements are resized as they should be.
The problem was not that the DataGridControls were encountering their own size constraints. They were in fact continuing to resize themselves as the window resized but they were getting it wrong. My guess is that their implementation relies on walking up the hierarchy or parent UI elements and sizing themselves in accordance to what they calculate their available space to be. I found that nothing short of dictating the exact width of one of the parent elements solves this. If the parent elements use star sizing, and these widths are constrained by column definitions to have a maximum or minimum width or height, the Xceed DataGridControl is oblivious and incorrectly requests a size greater than or less than what is available, even if it's been told to stretch to fit its parent control.
The only workaround I found that doesn't involve boycotting Xceed (which is very tempting) is to redesign the layout so that the first column doesn't grow with the rest of the window and is simply fixed at its minimum width:
<Grid Grid.Row="1" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="Red" />
<Grid Grid.Column="1" Background="Blue" />
</Grid>
It looks odd and disproportionately squished on large resolution screens, but any attempt to constrain the width while auto-sizing it leads to the behaviour described.
That is totally correct.
In your definition you define that the first columns width has to be at least 250. So 1* has to be at least 250 too. Your second columns width has to be the value of your first column multiplicated by 4. Sorry for my bad english, i hope you can understand.
I cant find an easy and fast solution for that. Maybe you have to bind the MaxWidht property of the second column to the ActualWidth property of the grid and than reduce that value by 250.
Related
I have a Grid inside a ScrollViewer (only vertical scrolling is enabled). I have a TextBox in that Grid, which ColumnSpan is 2, and its HorizontalAlignment is Stretch. Because of the ScrollViewer, if the user starts typing something really long, the TextBox will grow wider and wider, which I would like to avoid, it should be only as wide as the two columns it's spanning across, not widening them too.
I'm not sure how good of a practice would be to set it's MaxWidth to a constant, so I'd like to bind it instead to the two columns's ActualWidths.
In the column definitions:
<ColumnDefinition Width="1.3*" x:Name="grdCol1"/>
<ColumnDefinition Width="1.3*" x:Name="grdCol2"/>
The TextBox:
Width="{Binding ElementName=grdCol1, Path=ActualWidth}"
The question is, how could I bind it to grdCol1 + grdCol2's ActualWidth? Or should I even go down this road? Is there a preferred, maybe cleaner way to do so?
Turns out my ScrollViewer was at fault here.
NOT WORKING:
<ScrollViewer
HorizontalScrollBarVisibility="Hidden"
HorizontalScrollMode="Disabled"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Auto">
WORKING:
<ScrollViewer
HorizontalScrollBarVisibility="Disabled"
HorizontalScrollMode="Disabled"
VerticalScrollBarVisibility="Auto"
VerticalScrollMode="Auto">
You have to set the HorizontalScrollBarVisibility to Disabled, as Hidden is not enough for this purpose.
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.
I'm in the process of creating a UI, that's central component is a scrollviewer holding a stackpanel with a variable number of items. If there is not enough space on the screen, buttons on the left and right appear to allow clicking through the stackpanel using the scrollviewer. Note that the items are all of the same size.
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="LeftButton" Width="Auto"/>
<ColumnDefinition x:Name="Content" Width="*"/>
<ColumnDefinition x:Name="RightButton" Width="Auto"/>
</Grid.ColumnDefinitions>
This is working fine. However, I'm now required to display only full / complete items. So if there are more items in the stackpanel, than I can display on the screen I don't want to partial items on the right or left appear. I just want my scrollbutton to appear, indicating that there are more items available.
So, if a child is added to the stackpanel, the scrollviewer holding the stackpanel should see if there is enough space on the screen to display all items. If not it should reduce its width, so that the next (partially visible) item is hidden instead.
My question is: what's the best way to determine whether all items in the stackpanel can be displayed on the screen. And if not, how can I achieve hiding partial items probably displayed?
I have played around with the width of the Scrollviewer itself, relying on the SizeChanged event, but I'm not sure if this is the wisest method to achieve this behavior. Is it better to determine the MaxWidth of the scrollviewer on initialisation, set it accordingly and let it grow?
Thanks in advance,
curiosity
I think that since this is such a customized scroll viewer, then you don't need to use the default scrollviewer at all, but instead use your own control based on stackpanel that will show the items. You could even implement an animation so that when pressing the left or right buttons, it would scroll in a nice way.
When debugging my WPF programs I have noticed that when the window is the set size, the contols look just fine. But when the window is maximized, the content is positioned at the same place as if window has not resized. I want it so that the content and window resize proportionately. How can I do this? Sorry if it is a noobish question, but I'm kinda new in the WPF era.
The XAML code is not completely ready yet but here is some of elements:
<DockPanel>
<StackPanel DockPanel.Dock="Left">
...
</StackPanel>
<TabControl DockPanel.Dock="Right">
...
</TabControl>
<ListView>
...
</ListView>
</DockPanel>
Usually, this is because dimension values are set statically, rather than dynamically. Here's the static approach:
<RowDefinition x:Name="NavigatorRow" Height="120"/>
<RowDefinition x:Name="TaskPanelRow" Height="80"/>
Both rows will have fixed heights, and they won't resize with the window.
Here is the dynamic approach:
<RowDefinition x:Name="NavigatorRow" Height="1*"/>
<RowDefinition x:Name="TaskPanelRow" Height="80"/>
The bottom row still has a fixed height of 80, but the top row will expand to fill whatever space is available. In other words, the rows will resize with the window. Columns work the same way.
If I had three rows, I could do this:
<RowDefinition x:Name="NavigatorRow" Height="1*"/>
<RowDefinition x:Name="CalendarRow" Height="2*"/>
<RowDefinition x:Name="TaskPanelRow" Height="80"/>
The Navigator Row and the Calendar Row will share the available space, with the Calendar Row taking twice the height of the Navigator Row. You get the idea.
So, it's not the container you use, but how you size that container. The one exception, as noted above, is the StackPanel, which does not scale. Use a Grid instead, since it does scale.
Usually this is because the content is hosted in a container which has an explicitly set width and height - like Grid for example.
Post your Xaml or that answer is the best you will get!
Avoid using StackPanels they don't resize dynamically properly.
Ideally you should use a grid and specify percentages if you want things to resize proportionately.
Not sure why everyone is saying stackpanels don't resize dynamically. They handle resizing just like grids do. Just make sure you set your HorizontalAlignment="Stretch" (and/or VerticalAlignment) and the content will expand to fill the stackpanel size. I'm currently using a UI that consists of many nested stackpanels, horizontal and vertical resizing the window expands/contracts all the controls equally inside the window.
Well, you have to have some sort of container for your controls, right? If you're using Canvas and just position your controls absolutely inside there you're pretty much out of luck; this isn't very well for scaling interfaces.
However, there are various container controls that will layout whatever you put in them in certain ways. And if used properly, they scale with a resizing window, too. The Grid is pretty flexible, but StackPanel and DockPanel are very handy at times, too.
You can nest them, if you need.
Use WPF grid with the Widht and Height properties setupped with the "Number*" notion.
For example Width="0.6*", wich is not absolute height but proportional relation to the container. Generaly , if you want resizable content, avoid the fixed size properties as much as you can.
<Grid.RowDefinitions>
<RowDefinition Height="10*"></RowDefinition>
<RowDefinition Height="*" ></RowDefinition>
</Grid.RowDefinitions>
Good Luck.
I have a Panel whose Width can be resized during runtime:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="770*"/>
</Grid.ColumnDefinitions>
<panels:NavigationPanel x:Name="cmBar" Margin="2,2,0,2"
HorizontalAlignment="Left" Width="220"/>
<panels:DetailAreaPanel x:Name="detailGrid" Margin="224,2,2,2" />
</Grid>
When the program is closed, I want to save the new Width in the registry. So the program will load to the same size next time its opened. I have everything working except the Width, unless I hardcode the new Width. So I would assume that my save is wrong.
all[5] = cmBar.ActualWidth.ToString();
all[] is then wrote into the registry. No matter how the panel is resized cmBar.ActualWidth is always 220. Any ideas?
HorizontalAlignment="Stretch" will allow the control to size to its parent. "Left" just sizes to itself and leaves empty space to its right.
Aviad P. had one this right the .Width is what is causing the problem. The solution is is when i load the width to load it as .MaxWidth This will do the resizing but allow .ActualWidth to have the real width of the panel.
The little piece that says Width="220" sets the width to 220, and that will not change unless explicitly changed from the code-behind. Are you changing the panel's width in code-behind? If not - then its width really doesn't change, and stays at 220 throughout its lifetime.