scrollbar appears wrong on ItemsCotrol of a grid - wpf

I have Itemscontrol in the 3rd column of my grid which shows some set of buttons which gets loaded dynamically.
I wanted these contents (i.e. buttons) to occupy maximum width of Grid. and when contents exceeds Grid size, it will show vertical scrollbar.
I applied Scrollbar style to ItemsControl as follows :
<Style x:Key="ItemControlStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border>
<ScrollViewer HorizontalContentAlignment="Stretch"
CanContentScroll="True"
HorizontalScrollBarVisibility="Disabled"
Uid="ScrollViewer_9"
VerticalScrollBarVisibility="Auto">
<ItemsPresenter Margin="{TemplateBinding Padding}"
KeyboardNavigation.DirectionalNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Uid="ItemsPresenter_5" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have also applied HorizontalAlignment and VerticalAllignMent as "Stretch" for both ItemsControl as well as its parent i.e. Grid.
Output view I want is( 3rd column of grid)
Output I am getting is :
Scrollbar should appear after size exceeds
How to adjust these contents horizontally to Grid's max width?

Is it just a case of adding HorizontalAlignment=Stretch to ScrollViewer?
ie:
<Style x:Key="ItemControlStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border>
<ScrollViewer HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
CanContentScroll="True"
HorizontalScrollBarVisibility="Disabled"
Uid="ScrollViewer_9"
VerticalScrollBarVisibility="Auto">
<ItemsPresenter Margin="{TemplateBinding Padding}"
KeyboardNavigation.DirectionalNavigation="Cycle"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
Uid="ItemsPresenter_5" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

WPF Progressbar style text

I have a style for a progressbar that shows some text only on the PART_Indicator section:
<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14" MinWidth="200">
<Border Name="PART_Track" CornerRadius="15" Background="{StaticResource PressedBrush}" BorderBrush="{StaticResource SolidBorderBrush}" BorderThickness="1" />
<Border Name="PART_Indicator" CornerRadius="15" Background="#CEAC2D" BorderBrush="#CEAC2D" BorderThickness="1" HorizontalAlignment="Left" >
<Viewbox>
<TextBlock TextAlignment="Center" Background="Transparent" FontFamily="Times" Foreground="Black" Margin="2,2,2,2"
Text="{Binding ProgressText}"/>
</Viewbox>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have a few bars and each one should show a different kind of text (50%, 2/8, etc..) and that of course is handled by the VM.
My question is how to use this style for all the bars but differentiate only that textblock text. I presume the binding is not correct .. I probably need a TemplateBinding, but to what property?

In WPF, why is my button border not showing?

I've created the following style for buttons in XAML:
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="#FFFEFF" BorderBrush="white" BorderThickness="0.8" CornerRadius="3">
<Button Background="#FFFEFF" Foreground="#009999">
<ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Button.Effect>
<DropShadowEffect Color="#BABABA" ShadowDepth="2"/>
</Button.Effect>
</Button>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For some reason, the border changes are not displaying so I cannot change the corner radius. The drop shadow works great. This may be very simple, but I am stumbling through XAML and C# for the first time! I tired listing the border under a different setter in the style, but that only resulted in seeing the border under the squared edges of the button.
It looks like you will need to bring the border effect outside of the button and into the border element itself. By placing the border effect inside of the button, you are causing the effect to conform to the shape of the button, instead of the border, and since the button has square corners, it will always appear square, despite the border corners being rounded. Please see this post for an example: WPF style for buttons.
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="#FFFEFF" BorderBrush="white" BorderThickness="0.8" CornerRadius="3">
<Border.Effect>
<DropShadowEffect Color="#BABABA" ShadowDepth="2"/>
</Border.Effect>
<Button Background="#FFFEFF" Foreground="#009999">
<ContentPresenter Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Button>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

ItemsControl is preventing item content from expanding to fill its container

I am creating a WPF custom control that inherits from ItemsControl. In the ControlTemplate of my control I have an ItemsPresenter. The problem is that I need to be able to get content in the items presenter to fill the entire content area. In the code below I have a simplified example of the broken code and also what I am trying to accomplish. BTW setting HorizontalAlignment and VerticalAlignment to Stretch causes the content expand horizontally but not vertically.
<Window x:Class="yada"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768" Width="1024">
<Grid>
<Grid.Resources>
<Style TargetType="Border" x:Key="stepBorder">
<Setter Property="Background" Value="CadetBlue"></Setter>
<Setter Property="BorderBrush" Value="Green" ></Setter>
<Setter Property="BorderThickness" Value="2"></Setter>
<Setter Property="Padding" Value="25"></Setter>
</Style>
</Grid.Resources>
<TabControl Margin="0,20,0,0">
<TabItem Header="Broken">
<Border>
<ItemsControl>
<ItemsControl.Items>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}">
<TextBlock Text="Border fills small region near the top"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</ItemsControl.Items>
</ItemsControl>
</Border>
</TabItem>
<TabItem Header="Works">
<Border>
<Control>
<Control.Template>
<ControlTemplate>
<Border Style="{StaticResource stepBorder}" >
<TextBlock Text="Border fills entire control"></TextBlock>
</Border>
</ControlTemplate>
</Control.Template>
</Control>
</Border>
</TabItem>
</TabControl>
</Grid>
</Window>
Here is some code from my control. I cant include it all, there is too much. I think this is the relevant part however:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Wizard}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" x:Name="ContentRow" />
<RowDefinition Height="{Binding ElementName= NavButtonPanel,Path=ActualHeight}"></RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" x:Name="ContentScrollViewer" MaxHeight="{Binding ElementName=ContentRowHeight, Path=ActualHeight}">
<ItemsPresenter
x:Name="Presenter"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
</ItemsPresenter>
</ScrollViewer>
<Border Style="{TemplateBinding NavButtonPanelStyle}" Grid.Row="1" x:Name="NavButtonPanel">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" >
</StackPanel>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate></DataTemplate>
</Setter.Value>
</Setter>
As usual, just posting on SO gets me halfway to my answer.
It turns out the ItemsControl is using an evil stackpanel as a container for items. Fortunately there is a top-secret property called ItemsPanel that lets you change this. Just set it to a grid as shown below and you are in business.
In my case I am writing a custom control that inherits from ItemsControl so in the Style I add this property setter:
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid></Grid>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>

Binding a TextBlock back to ListBoxItem ItemSource

I have a ListBoxItem Style that I am trying to modify so that it will show character ellipsis when the list box is made to small. To do that I've had to get rid of the ContentPresenter in our code and replace it with a TextBlock. The ListBoxes that this is applied to are all bound via the ItemSource property.
Here is my code.
<Style x:Key="ListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="White"/>
<Setter Property="Margin" Value="0,0,0,0"/>
<Setter Property="Padding" Value="0,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border x:Name="Bd" SnapsToDevicePixels="true">
<!-- Before this used to be ContentPresenter but I switched it to TextBlock to get it the TextTrimming property. I can't find the right way to bind the data though.-->
<TextBlock Text="{TemplateBinding DisplayMemberPath}" TextTrimming="CharacterEllipsis" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<Rectangle x:Name="HoverRectangle"
Stroke="{StaticResource Gold}"
StrokeDashCap="Square"
StrokeThickness="0"
SnapsToDevicePixels="True" />
<Rectangle x:Name="KeyboardFocusRectangle"
Height="Auto"
SnapsToDevicePixels="True"
Stroke="{StaticResource BrightBlue}"
StrokeDashCap="Square"
StrokeThickness="0" />
</Grid>
<ControlTemplate.Triggers>
<!-- Bunch of Triggers in here -->
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My current TextBlock Text binding (Text="{TemplateBinding DisplayMemberPath}") is not working. What should the binding be in order to work correctly?
Your only reasonable choice here is to assume the data context of the ListBoxItem is a string, or can be displayed as such:
<TextBlock Text="{Binding}" .../>

wpf itemscontrol items outside of control

I have an own control which derives from itemscontrol with an own template. I am using a Canvas inside the itemscontrol as ItemsPanel. Why f.e. on resize of the window the items also can be outside of the itemscontrol?
Templates:
<Style TargetType="{x:Type local:Dashboard}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Dashboard}">
<Grid>
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
The items use this:
<Style TargetType="{x:Type local:Widget}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:Widget}">
<Grid Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="0" BorderThickness="2" BorderBrush="Black" Background="WhiteSmoke"
x:Name="Part_Header">
<ContentPresenter ContentSource="Header"/>
</Border>
<Border Grid.Row="1" BorderThickness="2" BorderBrush="Black" Background="WhiteSmoke">
<Grid>
<ContentPresenter />
<ResizeGrip x:Name="Part_Resize"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Cursor="SizeNWSE" />
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Depending on your alignment and margin settings, resizing a parent can cause children to move outside of a parent's boundaries. The easiest way I've found to check this is to load Blend and resize the parent, watching how contained controls move. By tweaking the anchors in Blend (which changes alignments and margins), you should be able to troubleshoot why they move.

Resources