Adjust a scrollviewer's width dynamically - c#

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.

Related

Controls do not resize when maximised but do when resized by dragging - wpf

Question is as per
WPF: when I maximize my window, controls do not resize which is unanswered.
I have a WPF form with some controls which are tied to at least two edges of the form. I have added code to sizechanged event which resizes controls as a ratio of form size. The code works well and when the form is resized by dragging the controls resize correctly.
When form is maximized the controls do not resize, save for vertically on the controls attached to both top and bottom of the window.
I have added similar code to the statechanged event however this does nothing. I have tried a straight TextBox1.Width = 300; but this does not change the size once maximised.
Ideally what I want is for say
TextBox1.Width = Window.width/3; TextBox1.Margin = My_Margin; Where My_Margin sets the left margin to 1/3 Window.Width. So that the textbox occupies the central third of the window.
EDIT: I understand that the GRID method was the way to go from the start of the project. Is there a workaround I can do at this stage in c# instead of having to rework the form?
EDIT: Have accepted the best answer, though it does not answer the actual question, as it looks like the only option I have.
I know that there is a way to resize controls once the form is maximized, I don't have time to find it and no good suggestions came forth.
Use a grid, define columns (with their width) and rows, and place the textbox using Grid.Row and Grid.Column properties. Also in a WPF Grid, * for Width and Height means proportional sizing.
So for instance if you have 2 columns defined like these ones
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="9*"></ColumnDefinition>
</Grid.ColumnDefinitions>
you are saying to wpf that the first column will occupy the 10% of the total available width, while the second 90%.

StackPanel is not scrolling

I want to put lots of controls inside a StackPanel and user can scroll up and down. I have a simple StackPanel inside a grid.
<Grid>
<StackPanel>
</StackPanel>
</Grid>
If I'm not wrong, I've seen that StackPanel scrolls, but now it is not working. Does it support scrolling or it is not supported at all? ( I prefer not to put it inside a ScrollViewer). thanks
Nothing really scrolls unless it has a ScrollViewer inside. When you do it like you're doing it now, you'll see only the items that fit on the screen, and others will be 'out of screen borders'.
So I'm afraid you'll have to add a ScrollViewer. It's actually a good thing that StackPanel doesn't scroll by default.

How to disable all the controls on windows phone by displaying a semi transparent control over the page?

I'd like to have some sort of semi transparent/translucent effect displayed over the entire page and then display my option buttons on top of it but I just can't figure out how and it's driving me nuts! I've seen it in plenty of wp8 apps so it is doable but I just don't know how!
Once this semi transparent/translucent effect is displayed, I want it to dissapeared if clicked on or if one of my option buttons is clicked, and restore the screen as it was or execute an action accordingly.
I've somehow managed to do it by setting the Background colors using a storyboard but strangely enough, once displayed and my options buttons appear, they look fine but once the storyboard is completed, the button then look disabled as well which just looks wrong!!
What is the proper way to give a "Disabled" effect as if you had a semi transparent dialog box displayed over a window.
Any ideas, suggestions or code would be appreciated.
Thanks.
You may be making this more complicated than it needs to be. Consider the following XAML for example:
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="ContentRoot">
...
</Grid>
<Grid x:Name="ContentOverlay" Background="#AA000000" Visibility="Collapsed">
...
</Grid>
</Grid>
Both ContentRoot and ContentOverlay will anchor at the top left of the LayoutRoot grid and span the row height. They will stack from furthest to closest in order of declaration, so ContentRoot will be rendered beneath ContentOverlay. Simply manipulate the Visibility of ContentOverlay based on user input.
Alternatively, you can set the Opacity for ContentOverlay to 0 along with collapsed visibility (required so it doesn't intercept hits to the ContentRoot child controls below) and fade it in and out using storyboarding in Blend. That probably looks like a slightly cleaner transition to a user, even if it's only 0.3 seconds long or so.
Use Blend to specify VisualStates (View | States. Then 'states' tab.) You can switch between states in code behind using VisualStateManager.GoToState. One state would be normal, the other all controls disabled.
Mike

Grid ColumnDefinition star-width is stretching beyond the parent container's bounds

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.

How can I get the size of a WPF panel that was changed during runtime?

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.

Categories