WPF: GridSplitter not visible but functions as expected - wpf

I am creating a new WPF Application where the main window has a grid inside a dock panel. The grid will have 3 columns and one row, out of which the middle column is dedicated for the GridSplitter. The other two columns have a dock panel each, which will have any content (to be created in run-time). My problem is that despite multiple approaches to make the GridSplitter visible, I have not been successful.
I have even followed tips given in this How To page in Microsoft documentation, but to no fruition:
https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-make-sure-that-a-gridsplitter-is-visible
Here is my XAML code:
<Window
...
Height="600"
Width="650">
<DockPanel LastChildFill="True">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="10"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<DockPanel Name="LeftDockPanel" Grid.Column="0" LastChildFill="True" Width="350" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="LightCyan">
</DockPanel>
<DockPanel Name="RightDockPanel" Grid.Column="2" LastChildFill="True" Width="300" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Azure">
</DockPanel>
<GridSplitter Width="5" Background="Red" Grid.Column="1" BorderBrush="Red"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Margin="3,0,3,0" ResizeBehavior="PreviousAndNext" Panel.ZIndex="1"/>
</Grid>
</DockPanel>
</Window>
I've attempted the following with my code:
Assigned a ZIndex=1 to the grid splitter while it shares a column with the LeftDockPanel
Dedicated a column explicitly for the splitter, assigning it a width
Ensured that the GridSplitter is the last control added to the grid
Combination of 2, 3 and 4 - As you see in the code.
On hovering the mouse in the appropriate area, the cursor does change to expose the gridSplitter, but it is never visible. Even the resizing actions are working as expected.
What am I missing or doing wrong that the GridSplitter is not visible?

Your issue is not reproducible. Maybe you have defined an implicit Style somewhere. Try to set the Template property to a custom template:
<GridSplitter Width="5" Background="Red" Grid.Column="1" BorderBrush="Red"
VerticalAlignment="Stretch" HorizontalAlignment="Center"
Margin="3,0,3,0" ResizeBehavior="PreviousAndNext">
<GridSplitter.Template>
<ControlTemplate TargetType="{x:Type GridSplitter}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"/>
</ControlTemplate>
</GridSplitter.Template>
</GridSplitter>

Related

Make textbox width automatically changable in Stackpanel which is in Border, WPF

I wanted to put Button in TextBox, but as I found it's not possible so I decided to do something like this:
Xaml for this looks as shown below:
<Border Grid.Row="4" Grid.Column="2" Margin="10,0,10,0"
BorderBrush="Gray" BorderThickness="1">
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}"
Width="245"/>
<Button Content="*" Width="15" BorderThickness="1"/>
</StackPanel>
</Border>
The problem I have is that, when I resize my window (decreasing width) my Button dissapears:
I want it to behave as DateTimePicker does. I have tried many ways to make TextBox width auto adjustable ( * in width isn't correct input, auto decreases width of TextBox, I also tried to define style resource in StackPanel resources for TextBox width, but it doesn't work too), but Haven't found correct way yet.
Replace the StackPanel with a Grid:
<Border Margin="10,0,10,0" BorderBrush="Gray" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}" />
<Button Grid.Column="1" Content="*" Width="15" BorderThickness="1"/>
</Grid>
</Border>
use Grid instead of StackPanel. Setting fixed size (Width/Height) is not a good idea for adaptive layout. Grid will allow TextBox to stretch.
one option is to have separate columns for TextBox and Button:
<Border Grid.Row="4" Grid.Column="2" Margin="10,0,10,0"
BorderBrush="Gray" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}" />
<Button Content="*" Grid.Column="1" Width="15" BorderThickness="1"/>
</Grid>
</Border>
alternatively place them in the same cell and let Button overlap TextBox (it will look like as a part of TextBox but can hide part of a long text):
<Border Grid.Row="4" Grid.Column="2" Margin="10,0,10,0"
BorderBrush="Gray" BorderThickness="1">
<Grid>
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}" />
<Button Content="*" HorizontalAlignment="Right" Margin="2" Width="15" BorderThickness="1"/>
</Grid>
</Border>

Issue with WPF WrapPanel inside a ScrollViewer

There are a number of similar questions on SO but so far I have not been able to resolve my problem using them.
I have a bunch of Controls inside a WrapPanel and the WrapPanel is inside a ScrollViewer. The ScrollViewer is inside a Grid.
I am trying to get all the <Border> controls in the WrapPanel to have an Orientation of 'Vertical' (so that they flow down and when there is no more space left vertically they wrap horizontally) with a HorizontalScrollBar that appears when there is no more space left Horizontally.
My code so far is as follows:
<Grid x:Name="configGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" Width="{Binding ElementName=configGrid, Path=ActualWidth}" Height="{Binding ElementName=configGrid, Path=ActualHeight}">
<WrapPanel HorizontalAlignment="Left" Orientation="Vertical" x:Name="ConfigWrapPanel" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollViewer}}, Path=ActualWidth}">
<Border BorderBrush="White" BorderThickness="1,1,1,1" CornerRadius="2" Margin="10">
<Expander IsExpanded="True" BorderThickness="0" Header="General">
// some controls here
</Expander>
</Border>
<Border BorderBrush="White" BorderThickness="1,1,1,1" CornerRadius="2" Margin="10">
<Expander IsExpanded="True" BorderThickness="0" Header="Another Block">
// some controls here
</Expander>
</Border>
// many more <border> blocks here....
</WrapPanel>
</ScrollViewer>
</Grid>
This almost works as expected, the various content flows vertically and when there is not enough room at the bottom it moves up and right and starts at the top again. But I never get any horizontal scrollbars and the controls just disappear off the right of the screen.
I'm sure this is something really simple I'm missing but I can't quite figure it out.
As a bit of further info, the various Border controls and sub elements are all of dynamic width and height (which is why I opted for a vertical orientation WrapPanel rather than Horizontal)
Any help would be greatly appreciated.
You have to remove the Width from your WrapPanel.
That width wants to stretch to infinity, which prevents the ScrollViewer from corrent measuring the boundaries of the WrapPanel resulting in never showing the ScrollBar.
Code below shows a working example:
<Grid x:Name="configGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" Height="{Binding ElementName=configGrid, Path=ActualHeight}">
<WrapPanel HorizontalAlignment="Left" Orientation="Vertical" x:Name="ConfigWrapPanel" >
<Border BorderBrush="White" BorderThickness="1,1,1,1" CornerRadius="2" Margin="10">
<Expander IsExpanded="True" BorderThickness="0" Header="General">
// some controls here
</Expander>
</Border>
<Border BorderBrush="White" BorderThickness="1,1,1,1" CornerRadius="2" Margin="10">
<Expander IsExpanded="True" BorderThickness="0" Header="Another Block">
// some controls here
</Expander>
</Border>
</WrapPanel>
</ScrollViewer>
</Grid>

GridSplitter not working when used in Grid present in DockPanel

I am stuck in resolving the GridSplitter to work.I have a DockPanel which has a Grid which is DockPanel.Dock="Bottom" and I have a GridSplitter which is also DockPanel.Dock="Bottom".
But the GridSplitter is not working and not allowing to resize the layout.
Maybe I am doing is completely wrong.Please correct me and tell me how can I perform this GridSplitter functionality.
Here is the Xaml I have:
<DockPanel Name="DocMain" LastChildFill="True">
<Grid DockPanel.Dock="Bottom">
<ScrollViewer Style="{StaticResource NotificationRegion}">
<TextBox Style="{StaticResource NotificationTextBlockStyle}" Name="Notification_Block"
Text="{Binding TxtBlkNotificationBar}"/>
</ScrollViewer>
<GridSplitter DockPanel.Dock="Bottom" Background="Black" Height="2" Width="Auto" ResizeDirection="Rows" HorizontalAlignment="Stretch"/>
</Grid>
</DockPanel>
Gridsplitter only works inside the grid its supposed to be splitting, for example
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="5"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<GridSplitter Grid.Column="1" ResizeBehavior="PreviousAndNext" BorderBrush="black" BorderThickness="5"/>
</Grid>
makes a grid with 3 columns with 2 columns for content and one for the splitter, gridsplitter is specified to be inside column #2 and resize the cells its placed between.

Border Styling applied to all the child elements recursively

I am new to WPF and need your help in resolving my styling issue.
I have applied border styling to GRID as below
<Border CornerRadius="5" BorderBrush="Gainsboro" BorderThickness="1,1,0,0" Name="border1" Margin="90,54,20,50" >
<Border BorderBrush="Gray" CornerRadius="5" BorderThickness="0,0,1,1" >
<Border.Effect>
<DropShadowEffect BlurRadius="10" Direction="-50" ShadowDepth="7" />
</Border.Effect>
<Border.Child>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="356*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="446*" />
</Grid.ColumnDefinitions>
<TextBox Name="TB1" Style="{StaticResource CustomTextBoxStyle}" Grid.Column="1" Margin="46,79,400,277" Grid.Row="1" />
<ComboBox Height="24" Name="comboBox1" Width="110" Grid.Column="1" Margin="304,86,232,276" Grid.Row="1" />
</Grid>
</Border.Child>
</Border>
</Border>
Then I have placed text box and combo box in the grid with custom styling.
The problem is parent GRID's border style is applied to child TEXTBOX along with its own custom style properties.
Could you please help me out in this?
Thanks
Bharat
As per MSDN doucment -
When a BitmapEffect is applied to a layout container, such as
DockPanel or Canvas, the effect is applied to the visual tree of the
element or visual, including all of its child elements.
But, there is a workaround as described here and here to have another border with same position but without the effect, that would resolve the problem -
<Grid>
<Border Margin="10" BorderBrush="Red" BorderThickness="1">
<Border.Effect>
<DropShadowEffect Color="Gray"/>
</Border.Effect>
</Border>
<Border Margin="10">
<!-- controls -->
</Border>
</Grid>

Validation Error Template Adorner is cut insight a ScrollViewer

i have the following problem. as far a i put my Textboxes in a scrollviewer my ValidationError Adorner get cut by the ScrollViewer. i found some answers to Adorner and ScrollViewer which say i need to retemplate my scrollviewer and add an adornerdecorator. but this makes no sense to me and it doesnt help either.
as far as i know should the Validation Adorner rendered in the nearest AdornerDecorator. the ScrollViewer by default has no AdornerDecorator. so does anybody know why my ValidationAdorner get cut?
I also looking for a solution :)
EDIT: it seems the ScrollContentPresenter which comes from the ScrollViewer Template cause the problem, because it has a AdornerLayer by default. Any ideas how to solve my issue?
EDIT2:
is there a way to create a new ScrollConntentPresenter Template without a Adornerlayer?
or is there a way to remove a the Adornerlayer from the VisualTree?
or can i force the Adornerlayer to render in a" higher/most top" AdornerLayer?
or can i have Scrolling Content without a ScrollViewer?
here is my xaml:
<UserControl>
<AdornerDecorator>
<Grid x:Name="RootControl">
<Grid.RowDefinitions>
<RowDefinition Height="auto" MinHeight="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid x:Name="main" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border x:Name="InputBorder" Grid.Column="0">
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<Grid x:Name="InputContainer" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
...some rows...
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
...some columns...
</Grid.ColumnDefinitions>
<TextBox .../><!--this Validation Adorner get cut by scrollviewer-->
</Grid>
</ScrollViewer>
</Border>
</Grid>
</Grid>
</AdornerDecorator>
</UserControl>
here is my Validation Template:
<ControlTemplate x:Key="ValidationTemplate" >
<DockPanel>
<AdornedElementPlaceholder Name="MyAdornedElement" />
<Grid>
<Border Background="{StaticResource BrushError}" Margin="3,0,0,0" x:Name="ErrorControl" BorderBrush="White" BorderThickness="1">
<TextBlock Margin="10,3,5,2"
Text="{Binding ElementName=MyAdornedElement,Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"
Visibility="{Binding ElementName=MyAdornedElement,Path=AdornedElement.Visibility}"
Foreground="White" FontWeight="Bold">
</TextBlock>
</Border>
<Path x:Name="path" Margin="3,0,0,0" Data="M 0,10 L 10,0 " Fill="{StaticResource BrushError}"
StrokeThickness="2" Stroke="White"
/>
</Grid>
</DockPanel>
</ControlTemplate>
the behavior is intended. A ScrollViewer is able to hide some of it's contents (ie the content lying in the extent). Showing an Adorner for such content that doesn't get clipped, results in a strange UI.
What you should be able to do in the ValidationTemplate though is putting the Grid element inside a Popup control. Please try that and report if it worked.

Resources