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.
Related
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>
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>
I have the following ControlTemplate that I am using in an ItemsControl. It is essentially a 3x3 Grid with a Path in the center and a Textbox/Textblock on top of it. When I use this, the Path takes up all of the space within the ItemsControl, and ignores the column/row definition constraints. Can anyone tell me why this is happening? I tried wrapping the Path in a Canvas but that didn't seem to help.
Thanks!
<controls:Toolbox x:Key="DrawingShapeTemplates"
DefaultItemSize="60, 60"
SnapsToDevicePixels="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ItemsControl.Items>
<Path Style="{StaticResource Square}"
ToolTip="Square Shape">
<controls:DesignerItem.MoveThumbTemplate>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1">
<TextBlock Text="Length" />
<TextBox MinWidth="{Binding RelativeSource={RelativeSource AncestorType=controls:DesignerItem}, Path=ActualWidth}" />
</StackPanel>
<Canvas Grid.Column="1"
Grid.Row="1">
<Path Style="{StaticResource Square_DragThumb}" />
</Canvas>
</Grid>
</ControlTemplate>
</controls:DesignerItem.MoveThumbTemplate>
</Path>
</ItemsControl.Items>
</controls:Toolbox>
The Style.
<Style x:Key="Square"
TargetType="Path"
BasedOn="{StaticResource StandardShapeStyle}">
<Setter Property="Data">
<Setter.Value>
<RectangleGeometry Rect="50 50 50 50" />
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Square_DragThumb"
TargetType="Path"
BasedOn="{StaticResource Square}">
<Setter Property="IsHitTestVisible"
Value="True" />
<Setter Property="Fill"
Value="Transparent" />
<Setter Property="Stroke"
Value="Transparent" />
</Style>
Edit
The source for this was downloaded from hereenter link description here. If you replace the <Path Style="{StaticResource Decision}" at line 469 with the following, you will get the same result that I do.
<Path Style="{StaticResource Decision}"
ToolTip="Decision">
<s:DesignerItem.MoveThumbTemplate>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="1*" />
<RowDefinition Height="3*" />
<RowDefinition Height="1*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="1">
<TextBlock Text="Length" />
<TextBox MinWidth="{Binding RelativeSource={RelativeSource AncestorType=s:DesignerItem}, Path=ActualWidth}" />
</StackPanel>
<Path Grid.Column="1"
Grid.Row="1"
Style="{StaticResource Decision_DragThumb}" />
</Grid>
</ControlTemplate>
</s:DesignerItem.MoveThumbTemplate>
</Path>
The following are pictures of what I am trying to accomplish and what the actual result is. I want to display a label and a text box on all four sides of the selected item when it is selected. Ultimately the label/textbox visibility will be databound to the DesignerItem.IsSelected dependency property, but that hasn't been wired up yet.
Expected result:
Actual result:
Typically Canvas do to clip it's children by default so you need to set it explicitly as ClipToBounds="True"
eg
<Canvas Grid.Column="1"
Grid.Row="1"
ClipToBounds="True">
<Path Style="{StaticResource Square_DragThumb}" />
</Canvas>
Update
Replace the Path element in FlowChartSymbols.xaml at line 469 with the following Grid
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Grid.Column="1">
<TextBlock Text="Length" HorizontalAlignment="Center"/>
<TextBox />
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType=s:DesignerItem}}"
Value="{x:Null}">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
<Path Style="{StaticResource Decision}"
Grid.Row="1" Grid.Column="1"
ToolTip="Decision">
<s:DesignerItem.MoveThumbTemplate>
<ControlTemplate>
<Path Style="{StaticResource Decision_DragThumb}" />
</ControlTemplate>
</s:DesignerItem.MoveThumbTemplate>
</Path>
</Grid>
this is how you can achieve the same. also fixed toolbox issue by adding a trigger to detect if it is inside a designer item or simply in a toolbox
I've got a simple WPF grid as an example, with each row having the same height (*). Each of three rows has a single textbox inside. I would like to know if it's possible, in XAML, to specify that when the textbox gets focus, the relevant row should increase to 2* (thus increasing the size for the textbox).
Thanks...
-Ben
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Background="AliceBlue" Grid.Row="0" />
<TextBox Background="AliceBlue" Grid.Row="1" />
<TextBox Background="AliceBlue" Grid.Row="2" />
</Grid>
</Window>
Are you just trying to make the font size bigger when any textblock gets focus? If yes then here's one way to do it
<Window.Resources>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="FontSize" Value="20"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Background="AliceBlue" Grid.Row="0" />
<TextBox Background="AliceBlue" Grid.Row="1" />
<TextBox Background="AliceBlue" Grid.Row="2" />
</Grid>
</Grid>
You can set the in the Style value for Grid.Row using Trigger like this:
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Grid.Row" Value="2" />
</Trigger>
</Style.Triggers>
</Style>
But to place all the elements in Grid necessary to set a value for Grid.Row locally. In this case, given the Dependency Property Value Precedence we have in the Style values that will be ignored.
I recommend you just set the Height for the TextBox, like so:
<Window.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="100" />
<Setter Property="Background" Value="AliceBlue" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Height" Value="200" />
<Setter Property="Background" Value="Beige" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="TextBox1" Grid.Row="0" />
<TextBox Name="TextBox2" Grid.Row="1" />
<TextBox Name="TextBox3" Grid.Row="2" />
</Grid>
Or hide/show TextBox via EventTriggers depending on the focus. To do this you just for each TextBox to create a EventTrigger with GotFocus and LostFocus events. For more information, please see this:
MSDN: EventTrigger
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