ScrollViewer not scrolling ItemsControl changes - c#

I am having a problem with a ScrollViewer in a modal dialog not changing scroll behavior when the ItemsSource of a ItemsControl inside the ScrollViewer changes.
When first creating the dialog the ScrollViewer's scrollbar behaves as expected with the size of the contents. When adding items to an ObservableCollection the ItemsControl is bound to the content changes but the ScrollViewer does not react to the change and activates the scrollbar.
Few items in ObservableCollection:
More items added to ObservableCollection :
After application restart:
<Grid x:Name ="Maingrid">
<Grid.Resources>
<ResourceDictionary>
<!--Style for RadButtons-->
<Style TargetType="telerik:RadButton" x:Key="RadButtonStyle">
<Setter Property="Margin" Value="10"/>
<Setter Property="Width" Value="95"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<!--end of Style for RadButtons-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/PS.Common.Presentation;Component/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="200" />
<RowDefinition Height="45" />
</Grid.RowDefinitions>
<!--List-->
<ScrollViewer x:Name="LeftScrollViewer" Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding BaysAndSystems, NotifyOnSourceUpdated=True}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0" IsChecked="{Binding Selected}" Content="{Binding Item.NameAndReference}" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<!--Buttons-->
<StackPanel Grid.Row="2" Grid.Column="0" Orientation="Horizontal" HorizontalAlignment="Center">
<telerik:RadButton Content="{x:Static resx:Resources.Copy}" Command="{Binding CopyCommand}"
CommandParameter="{Binding}" Style="{StaticResource RadButtonStyle}" />
<telerik:RadButton Content="{x:Static resx:Resources.Cancel}" Command="{Binding CopyCancledCommand}"
CommandParameter="{Binding}" Style="{StaticResource RadButtonStyle}" />
</StackPanel>
</Grid>
What can I do to get the ScrollViewer to react to the changed content?

Your ScrollViewer is in Grid.Row="1" which has a fixed height. Changed this grid's row height to *. It should work. Also you can try different values for VerticalScrollBarVisibility.

Your problem is that your row that holds your scrollviewer increases its height despite your definition of 200 px. Set it to "*" and set property MaxHeight="200" on your Row - it is going to be OK.
<Grid.RowDefinitions>
<RowDefinition Height="25" />
<RowDefinition Height="*" MaxHeight="200" />
<RowDefinition Height="45" />
</Grid.RowDefinitions>

Related

Stick to bottom of grid in an inner ContentControl

I have a main view with a secondary child view ChildViewModel inside it:
<Window {...}>
<Window.Resources> {...} </Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"> {...} </Grid>
<StackPanel Grid.Row="1"> {...} </StackPanel>
<ContentControl Grid.Row="2"
Content="{Binding ChildViewModel}"/>
</Grid>
</Window>
The ChildViewModel contains another grid of elements, with a Stack Panel of two buttons at the bottom. I would like these two buttons to be stuck to the bottom of the whole window.
I have tried this method, however it doesn't quite work as either the whole content control is at the bottom (with a large white gap at the top), or the buttons are at the bottom of the content control, but the content control itself is not at the bottom.
The following image should explain visually what I mean. The buttons are the two small rectangles that I would like at the bottom.
EDIT: Code of the Content Control:
<UserControl {..}>
<UserControl.DataContext>
<viewModels:ChildViewModel />
</UserControl.DataContext>
<Grid FocusVisualStyle="{x:Null}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.Resources>
{..}
</Grid.Resources>
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" FocusVisualStyle="{x:Null}">
{..}
</ScrollViewer>
<customViews:SwirlyThingy Grid.Row="1" {..}/>
<TextBlock Grid.Row="2" {..}/>
<TextBlock Grid.Row="3" {..}/>
<TextBlock Grid.Row="4" {..}}"/>
<!--The buttons I'd like at the bottom-->
<StackPanel Grid.Row=5"
VerticalAlignment="Bottom"
Orientation="Horizontal"
misc:MarginSetter.Margin="6">
<Button Command="{Binding PrepareForMigrationCommand}"
IsEnabled="{Binding CanMigrate,
UpdateSourceTrigger=PropertyChanged}">
<Button.Style>
<Style BasedOn="{StaticResource MajorControlButton}" TargetType="Button">
<Setter Property="Content" Value="Migrate" />
<Style.Triggers>
<DataTrigger Binding="{Binding PrepareForMigrationCommand.Execution.IsNotCompleted}"
Value="True">
<Setter Property="Content" Value="Migrating..." />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Command="{Binding PrepareForMultiMigrationCommand}"
Visibility="{Binding IsMultiMigration,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource BooleanToVisibilityConverter}}">
<Button.Style>
<Style BasedOn="{StaticResource MajorControlButton}" TargetType="Button">
<Setter Property="Content" Value="Run All" />
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>
</UserControl>
You want to take up all available space for the last item. In order to do this you would star size your last row of your top level grid.
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" /> <!-- Star size this one -->
</Grid.RowDefinitions>
In your control you could simply have two rows, one for all of your content which would be contained in a stackpanel (instead of multiple rows). And one row for your buttons. Your button panel would be aligned to the bottom.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Rectangle Height="20" Fill="Red"/>
</Grid>
<StackPanel Grid.Row="1">
<Rectangle Height="20" Fill="Orange"/>
<Rectangle Height="20" Fill="Yellow"/>
<Rectangle Height="20" Fill="Green"/>
</StackPanel>
<Grid Grid.Row="2"> <!-- simulating your custom control -->
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<!-- A bunch of content here
</StackPanel>
<StackPanel Grid.Row="1"
Orientation="Horizontal"
VerticalAlignment="Bottom">
<Button Content="Click Me!"/>
<Button Content="No, Me!"/>
</StackPanel>
</Grid>
</Grid>

Combine WPF Expander and GridSplitter and MinHeight

How can a GridSplitter and an Expander be combined nicely, while respecting MinHeight of the two areas above / below the GridSplitter?
For example:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="200" /> <!-- Main -->
<RowDefinition Height="Auto" /> <!-- GridSplitter -->
<RowDefinition Height="Auto" /> <!-- Expander -->
</Grid.RowDefinitions>
<ListBox>
<ListBoxItem>A</ListBoxItem>
<ListBoxItem>...</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Height="3" HorizontalAlignment="Stretch" />
<Expander Grid.Row="2" Header="Expander" IsExpanded="False">
<ListBox MinHeight="150">
<ListBoxItem>X</ListBoxItem>
<ListBoxItem>...</ListBoxItem>
</ListBox>
</Expander>
</Grid>
If I leave out the Expander, the GridSplitter works well and respects the MinHeight for the two row definitions.
If I leave out the GridSplitter (and move the second MinHeight to the seconds row definition), the Expander works well.
But when both are used, the MinHeight is not respected and the Expander just doesn't really work anymore.
Is there a simple fix?
Setup a trigger on the RowDefinition that changes the MinHeight based on the Expander state.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MinHeight="200" />
<!-- Main -->
<RowDefinition Height="Auto" />
<!-- GridSplitter -->
<RowDefinition Height="Auto" >
<RowDefinition.Style>
<Style TargetType="{x:Type RowDefinition}">
<Setter Property="MinHeight" Value="150" /> <!-- Default MinHeight -->
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyExpander, Path=IsExpanded}" Value="False">
<Setter Property="MinHeight" Value="24" /> <!-- MinHeight when Collapsed -->
<Setter Property="MaxHeight" Value="24" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
<!-- Expander -->
</Grid.RowDefinitions>
<ListBox>
<ListBoxItem>A</ListBoxItem>
<ListBoxItem>...</ListBoxItem>
</ListBox>
<GridSplitter Grid.Row="1" Height="3" HorizontalAlignment="Stretch" />
<Expander x:Name="MyExpander" Grid.Row="2" Header="Expander" IsExpanded="False">
<ListBox>
<ListBoxItem>X</ListBoxItem>
<ListBoxItem>...</ListBoxItem>
</ListBox>
</Expander>
</Grid>
By default the Row's MinHeight will be 150, however when the Expander is closed it will have both the Min and Max heights set to 24 (height of a default Expander), forcing its height to stay at the minimum value.

Margin difference in nested ListBox with DataTemplates

I have a problem with my ListBox. I have written several DataTemplates which I use in a ListBox. Each one of these contains a grid and may contain a nested ListBox depending on the item.
My problem is: The height of these nested ListBoxes seem to be different to the root ListBox's height. Additionally it seems, that there is sometimes one pixel margin to the element above.
Has someone encountered this problem, too and maybe solved it?
XAML-Code:
<!-- Template for SubData-Items -->
<DataTemplate x:Key="DataTemplate">
<Grid x:Name="baseGrid" Grid.Column="0" Grid.ColumnSpan="999" Background="Violet">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ElementName=Col0, Path=Width}" />
<ColumnDefinition Width="{Binding ElementName=Col1, Path=Width}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=Row0, Path=Height}"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Text="{Binding Bezeichnung}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="12" />
<Line Grid.ColumnSpan="999" Stroke="Black" X1="0" X2="{Binding ElementName=baseGrid, Path=ActualWidth, Mode=OneWay}" Y1="0" Y2="0" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
<!-- Template for Items -->
<DataTemplate x:Key="GroupDataTemplate">
<Grid Grid.ColumnSpan="999" Background="Blue">
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=Gantt, Path=GridRowHeight}" />
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="baseGrid" Grid.Column="0" Grid.ColumnSpan="999">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ElementName=Col0, Path=Width}" />
<ColumnDefinition Width="{Binding ElementName=Col1, Path=Width}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="{Binding ElementName=Row0, Path=Height}"/>
</Grid.RowDefinitions>
<TextBlock Grid.Column="1" Text="{Binding Bezeichnung}" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="12" />
</Grid>
<Grid x:Name="expandedGrid" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="999">
<ListBox x:Name="LBMaGruppen" ItemTemplate="{StaticResource DataTemplate}" ItemsSource="{Binding SubdataObjects}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Height="Auto" Margin="0,0,2,0"
ScrollViewer.CanContentScroll="false" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" BorderThickness="0" />
</Grid>
</Grid>
</DataTemplate>
<!-- Grid with ListBox -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="Row0" Height="34"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="Col0" Width="25" />
<ColumnDefinition x:Name="Col1" Width="*" />
</Grid.ColumnDefinitions>
<ListBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="999" ItemsSource="{Binding ItemSource, Mode=OneWay}"
ItemTemplate="{StaticResource GroupDataTemplate}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Height="Auto"
ScrollViewer.CanContentScroll="true"
ScrollViewer.IsDeferredScrollingEnabled="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
FontSize="10" />
</Grid>
qqbenq gave a very nice solution . Here is another way to do it.
the control templates of ListBox and ListBoxItem has padding inside their borders. Thankfully ListBoxItem border's padding can be control by a style like so:
<Style
TargetType="ListBoxItem">
<Setter
Property="Padding"
Value="0" />
</Style>
but unfortunately for the ListBox , you will have to override the default template with all of its details to change its internal border's hard-coded padding like this:
<Style
TargetType="ListBox">
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type ListBox}">
<Border
x:Name="Bd"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="0"
SnapsToDevicePixels="true">
<ScrollViewer
Focusable="false"
Padding="{TemplateBinding Padding}">
<ItemsPresenter
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger
Property="IsEnabled"
Value="false">
<Setter
Property="Background"
TargetName="Bd"
Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
</Trigger>
<Trigger
Property="IsGrouping"
Value="true">
<Setter
Property="ScrollViewer.CanContentScroll"
Value="false" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
One last note : remove the Margin that you added inside your xaml.
Solution complete
Add a Margin="-2,0,0,0" and a Padding="-1" to your "LBMaGruppen" named ListBox.
<ListBox x:Name="LBMaGruppen" ItemTemplate="{StaticResource DataTemplate}" ItemsSource="{Binding SubdataObjects}"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" Height="Auto" Margin="-2,0,0,0" Padding="-1"
ScrollViewer.CanContentScroll="false" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" BorderThickness="0" />
Also, the "root" element's height is binded to {Binding ElementName=Gantt, Path=GridRowHeight}, while the "sub" element's height to {Binding ElementName=Row0, Path=Height}, so this must cause the difference.
It seems that you have auto height set on all your ListBox. You could try setting the height to a specific size. EDIT: I see you already have ScrollViewer settings. I think setting the height of the box to a specific size instead of auto will do what you want.
As to the padding between elements see the ListBox.ItemContainerSyle which should allow you to set the margin between elements.

Making Background transparent for disabled TextBox

I have a disabled TextBox in a Grid.
The Grid has a BackgroundColor and I want the TextBox to just show some Text.
How can I get the Background of a disabled TextBox to be Transparent?
Here is what I have tried:
<UserControl x:Class="MyProject.Views.TextBoxView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="435"
d:DesignWidth="589"
FontFamily="Arial"
mc:Ignorable="d">
<Grid Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.Resources>
<Style x:Key="TextboxStyle_uniqueName" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="Control.IsEnabled" Value="False">
<Setter Property="Background" Value="Transparent" />
</Trigger>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="36" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="20*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="1"
Grid.ColumnSpan="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Red">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0"
Grid.Column="0"
Width="Auto"
Height="Auto"
Margin="0"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
BorderThickness="0"
FontFamily="Courier New"
FontSize="30"
Foreground="Black"
IsEnabled="False"
IsReadOnly="True"
IsTabStop="False"
Style="{StaticResource TextboxStyle_uniqueName}"
Text="BLAHBLAHBLAH" />
</Grid>
</Grid>
</UserControl>
If the Textbox is enabled, everything is okay and setting the Background works.
But as soon I disable it, I can no longer set the Background correctly.
Thought about some hack of Binding IsEnabled, so that the Background is set before.
-EDIT-
Strangly enough using TextBlock solves the issue. But I definitly have no style in the project that sets a background different from the default for TextBox.

Setting an initial width for an expander or listbox

In a previous question I had asked, I wanted to be able to move the gridsplitter to expand the expander which contains a list box of images so that when it expands, the images resize based on the amout of space available. With help i was able to get the resizing feature to work but the problem now is that when the program initially starts up, the images are full sized instead of thumbnail size. Is there a way to set an initial width of the expander so the images initially show up as thumbnails of about 175 pixels?
ColumnDefinitions:
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="25" Width="*" />
<ColumnDefinition MinWidth="5" Width="5" />
<ColumnDefinition Width="2*" />
<ColumnDefinition MinWidth="5" Width="5" />
<ColumnDefinition MinWidth="25" Width="*" />
</Grid.ColumnDefinitions>
0: Expander
1: gridsplitter
2: Text box
3: gridsplitter
4: Expander (Text box with images.)
XAML:
<GridSplitter
Name="gridSplitter2"
Width="10"
Margin="0,0,0,0"
Grid.Column="3"
IsEnabled="True"
HorizontalAlignment="Center"/>
<Expander
Style="{DynamicResource ExpanderStyle}"
Name="pictureExpander"
IsExpanded="True"
Grid.Column="4"
ExpandDirection="Left"
Collapsed="pictureExpander_Collapsed"
Expanded="pictureExpander_Expanded" >
<ListBox
Name="photoList"
ItemsSource="{Binding Source={StaticResource PhotoBin}}"
IsSynchronizedWithCurrentItem="True"
ScrollViewer.CanContentScroll="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Yellow" />
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="5"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Image
Name="thumbnailImage"
Source="{Binding FileLocation}"
Margin="5"
Stretch="UniformToFill"
StretchDirection="Both"
HorizontalAlignment="Stretch"
/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
I think you can play around with your ColumnDefinitions. Setting a Width on your fifth ColumnDefinition will give you a starting Width for it
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width="175"/>
</Grid.ColumnDefinitions>
<!-- Your other Controls.. -->
<GridSplitter Grid.Column="3" ... />
<Expander Grid.Column="4" ... />
</Grid>
Update
I'm unable to reproduce your problem. When I set Width="175" on the fifth ColumnDefinition it starts up with this width. Uploaded my sample app here: http://www.mediafire.com/?kjc9yqgmkq6dbiq

Categories