ScrollViewer does not react to ScrollToHorizontalOffset(0) - wpf

My ScrollViewer is auto scrolling to a middle offset, even when I try to force it back to a 0 offset it still aligns incorrectly
Here is part of the XAML:
<ScrollViewer x:Name="ScrollView" Grid.Row="0" Grid.Column="0" VerticalScrollBarVisibility="Auto">
<TreeView Grid.ColumnSpan="2" Name="LOBSummaryTree"
BorderThickness="0" DataContext="{Binding}">
<TreeView.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<common:VisibilityConverter x:Key="VisibilityConverter"/>
<common:TextStyleConverter x:Key="TextStyleConverter"/>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate DataType="ContentPresenter">
<StackPanel x:Name="StackGroups" Orientation="Horizontal">
<TextBlock Name="txtBox" Tag="{Binding}">
And the attempt from the code behind to force the offset:
var scrollViewer = this.ScrollView;
if (scrollViewer != null)
{
scrollViewer.InvalidateScrollInfo();
scrollViewer.ScrollToHorizontalOffset(0);
UpdateLayout();
}
What am I doing incorrectly, I want the alignment of the horizontal scollbar to be forced to the left on the initial load of the treeview?

Related

Items collection must be empty before using ItemsSource, wpf datagrid

I'm trying to add a Style to a datagrid, but I'm getting this error:
If I comment the style part everything works fine.
Here is my XAML, can anybody help me? thank you
Andrea
<dg:SelfBindingDataGrid Grid.Row="1" ItemsSource="{Binding Path=CurrentMachine.LNE_AUTOMATION_PARAM, Mode=TwoWay}"
SelectedItem="{Binding Path=CurrentAutParameter}" IsReadOnly="False">
<dg:SelfBindingDataGrid.Columns>
<dg:ExtDataGridComboBoxColumn Header="Spec. Element" Tag="CD_ELEMENT" Width="*"
TextSearch.TextPath="description"
SelectedValueBinding="{Binding Path=CD_ELEMENT, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
ItemsSource="{Binding Source={StaticResource ElementView}}"
SelectedValuePath="CD_ELEMENT"
DisplayMemberPath="description"/>
<dg:ExtDataGridTextColumn Header="Case File" Width="*" Tag="ID_CASE_TEST_FILE_TO_UPPER">
</dg:ExtDataGridTextColumn>
<dg:ExtDataGridNumericColumn Header="Case Index" Width="*" Tag="ID_INDEX"/>
<dg:ExtDataGridNumericColumn Header="MIN" Width="*" Tag="ID_RANGE_MIN"/>
<dg:ExtDataGridNumericColumn Header="MAX" Width="*" Tag="ID_RANGE_MAX"/>
<dg:ExtDataGridComboBoxColumn Header="Compile Method" Width="*"
ItemsSource="{Binding Source={x:Static local:AddMachineViewModel.ApproachList}, Mode=OneWay}"
SelectedValueBinding="{Binding Path=ID_COMMAND_FILE, Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}"
SelectedValuePath="ID_TYPE"
DisplayMemberPath="FL_TYPE"/>
</dg:SelfBindingDataGrid.Columns>
<Style TargetType="DataGridRow">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="LightBlue"/>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="LightBlue" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
</Style>
</dg:SelfBindingDataGrid>
</Grid>
</GroupBox>
You have added the Style as data item, but apparently wanted to add it to the Resources of the SelfBindingDataGrid:
<dg:SelfBindingDataGrid ...>
<dg:SelfBindingDataGrid.Resources>
<Style TargetType="DataGridRow">
...
</Style>
</dg:SelfBindingDataGrid.Resources>
...
</dg:SelfBindingDataGrid>
If you intended to set the Style of the SelfBindingDataGrid, it should look like this:
<dg:SelfBindingDataGrid ...>
<dg:SelfBindingDataGrid.Style>
<Style TargetType="dg:SelfBindingDataGrid">
...
</Style>
</dg:SelfBindingDataGrid.Style>
...
</dg:SelfBindingDataGrid>

Scrolling ListBox, Wrapping TextBlock

I am attempting to replace a piece of an existing Winforms project using WPF. Let's call this piece a 'log viewer'. Each log entry consists of a header and some body text. The viewer should display these in one long scrollable list.
The original (Winforms) logviewer works well when the number of log entries, and their size, is small, but it suffers from some problems when displaying large numbers of long entries; the WPF virtualizingstackpanel solves these problems, but WPF, or my lack of experience with it, is adding some problems of its own.
If I build the logviewer window around a ListBox, it works perfectly except for the fact that scrolling is by item rather than smooth scrolling 'by pixel'. I gather this can be fixed by moving to .Net 4.5 but that's not a simple option.
Alternatively if I build it around a TreeView, it scrolls perfectly but the text does not wrap; instead it forms one long line per paragraph.
Here's the xaml for the treeview version; it borrows heavily from this SO question where the style seems to be used to correct the non-wrapping issue. It scrolls beautifully, but it still doesn't wrap.
<Window x:Class="zCasesheet.wCasesheet"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gl="clr-namespace:System.Globalization;assembly=mscorlib"
Title="MainWindow" Height="440" Width="674">
<Window.Resources>
<Style x:Key="MyTreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Border Name="myBorder"
SnapsToDevicePixels="true"
CornerRadius="0,0,0,0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
BorderThickness="0"
BorderBrush="Transparent"
Height="Auto"
Margin="1,1,1,3"
Background="Transparent">
<ContentPresenter Grid.Column="1" x:Name="PART_Header" HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" ContentSource="Header"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Name="grCasesheet" Background="#FFF6E7C9">
<Grid.RowDefinitions>
<RowDefinition Height="356*" />
<RowDefinition Height="45" />
</Grid.RowDefinitions>
<TreeView HorizontalAlignment="Stretch" Margin="2,2,2,0" VerticalAlignment="Top" Name="lstNarratives" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.CanContentScroll="True" >
<TreeView.ItemTemplate >
<DataTemplate >
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Grid.Row="0" Background="Honeydew" HorizontalAlignment="Stretch" BorderBrush="Black" Text="{Binding Path=HeaderText, StringFormat=d, ConverterCulture={x:Static gl:CultureInfo.CurrentCulture} }"/>
<TextBlock Grid.Row="1" TextWrapping="Wrap" HorizontalAlignment="Stretch" Text="{Binding Path=BodyText}" Margin="10,10,10,10"/>
</Grid>
</DataTemplate >
</TreeView.ItemTemplate >
</TreeView>
</Grid>
I've also tried xaml based on this SO answer, but I can't get that to work either - it still scrolls by item.
Any help much appreciated.

Adding image on top of ListBoxItem in WPF

I have a ListBox with some ListBoxItems. Each ListBoxItem contains some text and a background image. When the user clicks a ListBoxItem I want to add an image on top of the ListBoxItem (it decorates the item with some additional looks).
I'm looking for a way to overlay the image onto the clicked ListBoxItem. That's the code I have so far:
<ListBox Margin="0,34,0,25.113" Background="{x:Null}" BorderThickness="0">
<ListBoxItem Content="First Item" Height="71.96" Margin="0,10,0,0">
<ListBoxItem.Background>
<ImageBrush ImageSource="Untitled-4.png"/>
</ListBoxItem.Background>
</ListBoxItem>
</ListBox>
Put your ListBoxItem.Content in a panel which allows overlapping controls, such as a Grid, and make your top image's Visibililty be based on ListBoxItem.IsSelected
<ListBox.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ListBox.Resources>
<ListBoxItem Height="71.96" Margin="0,10,0,0">
<ListBoxItem.Background>
<ImageBrush ImageSource="Untitled-4.png"/>
</ListBoxItem.Background>
<Grid>
<TextBlock Text="First Item"
VerticalAlignment="Center" HorizontalAlignment="Center" />
<Image Source="SomeImage.jpg"
Visibility="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}},
Converter={StaticResource BooleanToVisibilityConverter}}" />
</Grid>
</ListBoxItem>
Edit
You can also remove the blue background for the SelectedItem by overwritting the HighlightBrush Color and making it Transparent
<ListBox.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</Style.Resources>
</Style>
</ListBox.Resources>

Horizontal Scrollbars on a Fluid Listbox

What I want: To get the darn horizontal scrollbar to appear. I will be editing it a bit just so i fits the rest of the app's style scheme, but not too much.
What I have
Here is the code for the listbox as of now. Everything runs perfectly except the scrollbars dont appear. You might say... "well you dont have a scrollviewer anywhere", but I have tried inserting a scrollviewer in numerous places and still no luck.
The Listbox Code:
<ListBox ItemsSource="{Binding Items}" ItemTemplate="{StaticResource itemsdatatemplate}" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ItemsPanel="{StaticResource HorizontalListBoxTemplate}" ItemContainerStyle="{StaticResource TransparentListBox}" VerticalAlignment="Center" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" />
The 'TransparentListBox' (to shut-up the selected background color):
<Style x:Key="TransparentListBox" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="HoverBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<Border x:Name="SelectedBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<ContentPresenter></ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Horizontal List Box (to make the listbox Horizontal, rather than standard vertical)
<ItemsPanelTemplate x:Key="HorizontalListBoxTemplate">
<StackPanel Orientation="Horizontal">
</StackPanel>
</ItemsPanelTemplate>
The Datatemplate (to actually show the Items)
<DataTemplate x:Key="itemsdatatemplate">
<local:ListItemControl HorizontalAlignment="Left" VerticalAlignment="Top" DataContext="{Binding}"/>
</DataTemplate>
I have a feeling its going to be a simple addition, but Thanks in advance.
Update
It looks like the scrollbars now do appear with this:
<Style x:Key="ScrollingListBox" TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Visible">
<ItemsPresenter></ItemsPresenter>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
But they do not function accordingly. They feel... broken. However, if one was to define a static width (say 300) of the grid, then the ScrollViewer acts perfectly. Right now I have a completely fluid layout (meaning things stretch to fill), is this not acceptable for scrollviewers?
When you create your own template, you have to define the ScrollViewer in there and use an ItemPresenter instead of a ContentPresenter.
<Style x:Key="TransparentListBox" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Border x:Name="HoverBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<Border x:Name="SelectedBorderBackgroundBrush" BorderThickness="1" Margin="0,0,25,0" Background="Transparent"/>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Visible">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

How to style a WPF Expander Header?

I would like to apply a style on a WPF Expander Header. In the following XAML I have an Expander but the style is for all of it not just for the header.
Thanks.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640"
>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Expander">
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BackBrush}"/>
</Style>
</StackPanel.Resources>
<Expander>
<StackPanel>
<TextBlock>Bike</TextBlock>
<TextBlock>Car</TextBlock>
<TextBlock>Truck</TextBlock>
</StackPanel>
</Expander>
</StackPanel>
</Page>
I have combined some XAML from Josh Smith and MSDN and came up with a solution. Indeed, the control (al least the header) must be retemplated.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400">
<StackPanel>
<StackPanel.Resources>
<Style TargetType="Border" x:Key="RacePitBorderStyle" >
<Style.Resources>
<LinearGradientBrush x:Key="BackBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#EF3132" Offset="0.1" />
<GradientStop Color="#D62B2B" Offset="0.9" />
</LinearGradientBrush>
</Style.Resources>
<Setter Property="Background" Value="{StaticResource BackBrush}"/>
</Style>
<DataTemplate x:Key="titleText">
<Border Style="{StaticResource RacePitBorderStyle}" Height="24">
<TextBlock Text="{Binding}"
Margin="4 0"
VerticalAlignment="Center"
Foreground="White"
FontSize="11"
FontWeight="Normal"
Width="{Binding
RelativeSource={RelativeSource
Mode=FindAncestor,
AncestorType={x:Type Expander}},
Path=ActualWidth}"
TextWrapping="Wrap"/>
</Border>
</DataTemplate>
<Style TargetType="{x:Type Expander}">
<Setter Property="HeaderTemplate" Value="{StaticResource titleText}"/>
</Style>
</StackPanel.Resources>
<Expander Name="hcontCtrl" Header="This is the header.">
<StackPanel>
<TextBox>This is a textbox</TextBox>
<Button>A button</Button>
</StackPanel>
</Expander>
</StackPanel>
</Page>
I think Vasile's answer is on the right track, but it seems like it does a lot more than the original poster needed. All the original question was asking to do was to change the background of the header. While the change presented does do that, it also does other things.
One of these other things is to replace the default implementation, I believe a ContentPresenter, with a TextBlock. So what happens when later we change our Expander so that the header is more complicated? Maybe something like:
<Expander>
<Expander.Header>
<StackPanel>
<Border height="5" width="5" Foreground="Blue"/>
<TextBlock>Ha!</TextBlock>
</StackPanel>
</Expander.Header>
</Expander>
I don't know, but it's not good. Instead, I think we want to keep this simple.
<DataTemplate x:Key="expanderHeader">
<ContentPresenter
Content={Binding}
TextBlock.Background={StaticResource myBrush}/>
</DataTemplate>
<Style TargetType="Expander">
<Setter Property="HeaderTemplate" Value="{StaticResource expanderHeader}"/>
</Style>
That way when someone puts something that is not just text in our styled expander, we don't break. If you want to make sure you wrap the entirety of what they do with this background, which is probably desired, that would look like:
<DataTemplate x:Key="expanderHeader">
<Border Background={StaticResource myBrush}>
<ContentPresenter Content={Binding}/>
</Border>
</DataTemplate>
Depends what you want to style -- you can style any part of it. If you want to change the content in the header, just place all your UI in the Expander.Header property, and it'll show in the header area.
if that does't meet your needs, you probably need to re-template the control. Take a look at the control templates shipped in WPF here

Resources