Overlay Grid on top of Image inside ScrollViewer - c#

I have the following markup:
<ScrollViewer>
<StackPanel Orientation=Vertical>
<Image />
<Grid />
<ItemsControl />
</StackPanel>
</ScrollViewer>
Okay so the image is an animated loading gif. When an event is completed the program displays the grid and the items control as well, and the user is able to scroll up and down.
In order to do this currently I just set the image to Visiblity='Collapsed' and the Grid and the ItemsControl to Visible. How can I layer them so that the image is always underneath, and the grid and the items control are on top - so that when I fade out the grid and the items control the image appears underneath?
I know that there is an option for Z-Index, I tried placing the Image, Grid and ItemsControl inside a canvas and setting the Panel.ZIndex property but it didnt seem to work - for one when I set the opacity on the Grid to .5 I couldn't see the image underneath, and also the Grid didn't fill the space either (I need it to stretch to the size of the form).

This should work:
<ScrollViewer>
<Grid>
<Image/>
<StackPanel>
<Grid/>
<ItemsControl/>
</StackPanel>
</Grid>
</ScrollViewer>

Related

Issue with ScrollViewer in WPF

I am working on a WPF application and using a scrollViewer to view the content that is offlimit the screen area. Working fine, no issues.
But if my window contains a Listbox or Grid or anything like that and that control has many records then instead of adding a scrollbar to itself, it just increase the height of the control and window itself because scrollviewer believes it needs to extend.
I don't want to hardcode the listbox's height, because that make it same in different resolutions, i want to make it increase its height but not always as scrollviewer make it do so.
Thanks
You can't include a variable height/width object inside a ScrollViewer without setting the height/width of the viewer.
The scroll viewer effectively has infinite height so the grid expands to fill the "available" space - hence the effect you are seeing. As #JoeWhite says in his comments, the ScrollViewer is a container that can be as tall as it needs to be to hold all of its content. Anchoring wouldn't help - in effect, your ListBox already is anchored, it's just anchored to something that says "oh, I'll be whatever size you need me to be".
You'll need to either restrict the height, move the ListBox outside the ScrollViewer or use something other than a ScrollViewer.
Again quoting #Joe "These are the hazards of putting a scrolling area inside another scrolling area - it's poor usability and it's hard to define the behaviour."
You can wrap ScrollViewer into Grid, and bind scrollviewer's Width and Height properties to grid's ActualWidth and ActualHeight. So the scrollviewer will have fixed size equal to the size of the grid which will change when window resize.
Example:
<Grid x:Name="LayoutRoot" Background="White">
<Grid Background="#FFF1F1F1" Height="49" VerticalAlignment="Top">
<Button Content="Обзор" Margin="0,13,175.25,0" VerticalAlignment="Top" FontSize="14.667" HorizontalAlignment="Right" Width="95.147">
</Button>
<Label Content="{Binding DocPath, Converter={StaticResource FileNameConverter}, FallbackValue=Выберите файл, TargetNullValue=Выберите файл}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="342.603" Margin="10,10,0,0" Height="33"/>
<Button Content="Загрузить данные" HorizontalAlignment="Right" Margin="0,13,10,0" VerticalAlignment="Top" Width="151.147" FontSize="14.667">
</Button>
</Grid>
<Grid x:Name="scrollBorder" Margin="10,54,10,10">
<ScrollViewer x:Name="LogScroller" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
HorizontalAlignment="Left" VerticalAlignment="Top"
Height="{Binding ActualHeight, ElementName=scrollBorder}" Width="{Binding ActualWidth, ElementName=scrollBorder}" >
<ItemsControl ItemsSource="{Binding Log}" />
</ScrollViewer>
</Grid>
</Grid>

Hide control when another control overlaps it

I am having pretty big problem with windows forms controls hosted in WPF. When, for example, user scrolls the window, the hosted control goes on top of the window, although it should be hidden.
I know this is known problem, and default behavior of hosted controls, but I think it can be solved if control's visibility is somehow binded with: whether other controls overlap it, or not. If other controls are overlapping, it should become Collapsed or Hidden, if not, it should be Visible.
I made some kind of solution for this, but I did it on ScrollChanged event of a ScrollViewer and it works only in special situations. If somebody knows how to achieve that with binding, so it can be applied to any hosted control, please share your ideas.
For this same problem, we implemented something curious...
Windows forms host is unaffected by Z-order so scroll viewer wont be able to partially hide/ clip it for the area which is visible under the scrollviewer.
So we had two options...
Use Windows form host to host rest of the WPF UI in it which means we reverse the ownership of the UI. The WindowsFormsHost must host all the UI in it having a WinForms based scroll viewer which in turn will host the WPF UI.
Implement a scroll offset for calculated height of the windows forms host and when user scrolls add this offset to the scrollviewer's position and hide the windforms host yourself (Visibility = Hidden and NOT Collapsed). This way it gives an effect that you cannot partially scroll a winforms host but that scroll it completely off the scroll viewer. And because winformshost is Hidden (not collapsed) it continues to occupy that much height inside the invisible area under the scroll viewer (thereby maintaining its scroll position).
Let me know if this guides you in correct direction.
You can do a little trick. When you declare an WindowsFormsHost, it's parent is first HWND component. Usually it's root window. So, clip area for controls is whole window.
I'll show an example with WPF ScrollViewer.
<Window>
<Grid>
<ScrollViewer Margin="20,50">
<ItemsControl ItemsSource="{StaticResource StringArray}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WindowsFormsHost>
<wf:Button />
</WindowsFormsHost>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Window>
In this case behaviour will be like you described. Buttons will be out of ScrollViewer bounds.
But there's a way to create "intermediate" HWND item to clip WinForms area over ScrollViewer. Just place another WindowsFormsHost with ElementHost like below:
<Grid>
<WindowsFormsHost Margin="20,50">
<ElementHost x:Name="This is clip container">
<ScrollViewer>
<ItemsControl ItemsSource="{StaticResource StringArray}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WindowsFormsHost>
<wf:Button />
</WindowsFormsHost>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</ElementHost>
</WindowsFormsHost>
</Grid>
Now clip area for buttons is ElementHost and WinForms Buttons will be clipped by it on scrolling.
Also you can create ControlTemplate for ContentContol and reuse it where you need it.
<ControlTemplate x:Key="ClipConteiner" TargetType="{x:Type ContentControl}">
<WindowsFormsHost>
<ElementHost>
<ContentPresenter />
</ElementHost>
</WindowsFormsHost>
</ControlTemplate>
<Grid>
<ContentControl Template="{StaticResource ClipConteiner}" Margin="20,50">
<ScrollViewer>
<ItemsControl ItemsSource="{StaticResource StringArray}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WindowsFormsHost>
<wf:Button />
</WindowsFormsHost>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</ContentControl>
</Grid>

Image height inside Stack Panel

I'm designing a imaging gallery with Scroll Viewer and Stack Panel in WPF like the following:
<ScrollViewer x:Name="ShopsScroll" Grid.Row="1" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<StackPanel x:Name="stackPanel" Margin="0" Orientation="Horizontal" Height="Auto">
<Image Source="Images/1F/L1_angesb.jpg"/>
<Image Source="Images/1F/L1_chanel.jpg"/>
<Image Source="Images/1F/L1_dior.jpg"/>
<Image Source="Images/1F/L1_gucci.jpg"/>
<Image Source="Images/1F/L1_LV.jpg"/>
<Image Source="Images/1F/L1_nike.jpg"/>
</StackPanel>
Since the image is large in size, I would like to resize them to fit the height of the StackPanel. However, when I set the value of height in StackPanel as "Auto", it just used the height of the image, not its parent ScrollViewer. If I set a fix value to StackPanel, the problem seems being fixed, but I need to use my application in different size of screen in full screen. Thus, it should adapt different size but not hard code a fix value.
How I I do it?
You could use an element binding to bind the height of your images to the height of the StackPanel element. Sorry I can't test this code right now, but try something like
<Image Source="Images/1F/L1_nike.jpg" Height="{Binding ElementName=ShopsScroll, Path=Height}" />
See MSDN documentation on the Binding.ElementName property.
This property is useful when you want to bind to the property of another element in your application. For example, if you want to use a Slider to control the height of another control in your application, or if you want to bind the Content of your control to the SelectedValue property of your ListBox control.
Try to set HorizontalAlignment = "Stretch" and VerticalAlignment = "Stretch" for stackpanel
In my opinion better to have ItemsControl with images in it in your case
<ItemsControl HorizontalContentAlignment="Stretch">
<Image Source="Images/1F/L1_angesb.jpg"/>
<Image Source="Images/1F/L1_chanel.jpg"/>
<Image Source="Images/1F/L1_dior.jpg"/>
<Image Source="Images/1F/L1_gucci.jpg"/>
<Image Source="Images/1F/L1_LV.jpg"/>
<Image Source="Images/1F/L1_nike.jpg"/>
</ItemsControl>
Hope this helps

Scroll bar, if Items exceed inside itemControl

I have ItemControl
It displays one panel for each record inside ObservableCollection.
My Problem is….
When size of ObservableCollection increase window can’t accommodate more panels so it displays only first six panels.
So criteria, One panel for each record inside ObservableCollection,couldn't be accomplish.
So, I need to have scroll bar so I can access each panel.
How does it can be implement?
See one screen shot below and Code of It Here
Thanks......
You need to host your panel within a ScrollViewer. This allows it to grow beyond the space available to it, whilst the ScrollViewer adds a Scrollbar.
You can do this by modiyfing the ItemsControl template:
<ItemsControl>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
Put any controls you want to have scrollbars into the ScrollViewer. Example taken from MSDN:
<ScrollViewer HorizontalScrollBarVisibility="Auto">
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock TextWrapping="Wrap" Margin="0,0,0,20">Scrolling is enabled when it is necessary.
Resize the window, making it larger and smaller.</TextBlock>
<Rectangle Fill="Red" Width="500" Height="500"></Rectangle>
</StackPanel>
</ScrollViewer>

Silverlight TreeView ScrollBars disappear inside a StackPanel

I'm building a project that loads data from a webservice into a TreeView Control. When the TreeView is contained on the LayoutRoot grid by itself and it's height is set to Auto, if the contents extend beyond the vertical or horizontal limits of the treeview scrollbars appear automatically, as expected.
If that same TreeView control is placed inside a StackPanel, it's behavior changes. When data extends past it's limits, no scrollbar appears and data simply clips off the edge with no access to it. If I manually set the height of the TreeView in this scenario, the scrollbars will appear again as expected.
Clearly there seems to be some interaction between the StackPanel and TreeView that I'm not seeing.
Can anyone explain this and suggest an appropriate way to handle the situation?
Per request in comments:
The following XAML works fine and renders scrollbars as expected (notice the Height on the TreeView is Specified):
<StackPanel >
<controls:TreeView ItemTemplate="{StaticResource MainEntryIndexTemplate}"
x:Name="CodeBookIndexTreeView" Height="500" />
</StackPanel>
The following also displays scrollbars as expected (notice no StackPanel, but the TreeView's Height is set to Auto):
<controls:TreeView ItemTemplate="{StaticResource MainEntryIndexTemplate}"
x:Name="CodeBookIndexTreeView" Height="Auto" />
Finally, this code fails in that the TreeView will not display scrollbars and data scrolls off the bottom and/or right hand side of the control (notice the TreeView is in a StackPanel and the TreeView's Height is set to Auto):
<StackPanel >
<controls:TreeView ItemTemplate="{StaticResource MainEntryIndexTemplate}"
x:Name="CodeBookIndexTreeView" Height="Auto" />
</StackPanel>
Cheers,
Steve
Managed to get this one figured out with some help from the Silverlight.net forums. You can read the original question and answer here. It turns out that a StackPanel oriented vertically (the defaul orientation) will give infinite size to its children, so since the TreeView has infinite size, the scroll bars will never display. This does NOT happen when using a grid as your layout element.
The following XAML will render the TreeView scroll bars as expected. (Notice that the TreeView is contained in row 2 of a Grid, not a StackPanel and that the Height of the TreeView is set to Auto.) There are some additional controls in this code snippet because that was the reason for the extra container in the first place:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="Enter Search Term" />
<TextBox x:Name="SearchTermTextBox" Width="200" KeyUp="SearchTermTextBox_KeyUp"/>
</StackPanel>
<Button x:Name="SearchButton" Content="Search" Click="SearchButton_Click" Width="100"
HorizontalAlignment="Left" Grid.Row="1" />
<controls:TreeView ItemTemplate="{StaticResource MainEntryIndexTemplate}"
x:Name="CodeBookIndexTreeView" Height="Auto" Grid.Row="2" />
</Grid>
Yeh - StackPanels don't seem to be a great control for containing variable sized objects.
Similarly; I have had trouble with DataTemplates composed of textblocks within a stackpanel, used as ListItem templates within a ListBox. Intention was for the text block to wrap, but instead it just continues beyond the bounds of the list box, for which there is no horizontal scroll. Best I've managed so far was to fix the width of the Grid containing the stackpanels but not yet found a satisfactory solution.. would love to know if there is one!

Categories