Operating a slider inside a ListBox by touch - wpf

I have an ItemTemplate of a ListBoxItem that contains a Slider. The UI should be operated on a touch screen. However, the slider doesn't work - the thumb cannot be dragged.
The problem can be demonstrated like this:
<StackPanel>
<Slider Height="40" Width="300" Margin="20,10,20,10"/>
<ListBox>
<Slider Height="40" Width="300" Margin="20,10,20,10"/>
</ListBox>
</StackPanel>
The slider inside the ListBox cannot be dragged by touch (although it works for mouse or keyboard input). The other slider outside of the ListBox works just fine (mouse, keyboard, touch).
What needs to be done to "enable" the slider inside the ListBox for touch input?

The accepted answer of Slider \ ScrollViewer in a touch interface not working properly will help here as well.
This is probably due to the ListBox and ItemsControl containing a ScrollViewer internally. Obviously this ScrollViewer is important to drag the ListBox itself (so I cannot get rid of it). However, the ScrollViewer can be tricked by the CustomThumb class of the other post.
Replacing the Thumb in the style is as easy as:
<Window
...
xmlns:l="clr-namespace:WpfApplication1"
...>
<Window.Resources>
...
<Style x:Key="SliderStyle1" TargetType="{x:Type Slider}">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Slider}">
...
<Track x:Name="PART_Track" Grid.Row="1">
<Track.Thumb>
<l:CustomThumb x:Name="Thumb" .../>
</Track.Thumb>
</Track>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
You can do this by editing the style created by Expression Blend.

Related

Ensuring AdornmentDecorator within a ContentPresenter, but without a ControlTemplate

I've searched around quite a bit and can't seem to crack this nut.
I've got an app with a main view that changes dynamically, and to do this I use content presenter with a binding to a control:
<ScrollViewer Grid.Column="2" x:Name="StepScrollViewer">
<StackPanel Margin="20,20,20,500">
<ContentPresenter Content="{Binding MainControl}"/>
</StackPanel>
</ScrollViewer>
Then I change the MainControl at runtime in my view model. The problem is that the controls getting bound don't reliably display their error templates... I suspect it is for the reasons discussed here:
Validation ErrorTemplate not showing on data errors
But the fix for this problem doesn't seem to work for me because I'm not using a control template around my content presenter. When I wrap an AdornmentDecorator tag around my content presenter, it doesn't seem to fix the problem. It DOES work if I put an AdornmentDecorator inside each control I load into the contentpresenter (as the root element), but I'd like to avoid this repetition if possible.
Any insights?
UPDATE
I tried this approach suggested by Dennis, but to no avail. The control binds okay, but it works no better than the current approach (also shown commented below). Note: I tried it both with the AdornerDecorator as a singleton element the way Dennis has it, and surrounding the ContentPresenter, as shown below. Neither show any difference - the adorners around my controls all disappear when the MainControl binding is changed.
<UserControl.Resources>
<Style x:Key="MainContentControl" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Grid>
<AdornerDecorator>
<ContentPresenter Content="{Binding MainControl}"/>
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
.....
<ScrollViewer Grid.Column="2" x:Name="StepScrollViewer">
<StackPanel Margin="20,20,20,500" >
<ContentControl Style="{StaticResource MainContentControl}"/>
</StackPanel>
</ScrollViewer>
<!-- THE BELOW WORKS IF I SURROUND EACH BOUND CONTROL WITH adornerdecorator -->
<ScrollViewer Grid.Column="2" x:Name="StepScrollViewer">
<StackPanel Margin="20,20,20,500">
<ContentPresenter Content="{Binding MainControl}"/>
</StackPanel>
</ScrollViewer>
-->
Instead of using a ContentPresenter directly, I would instead use a ContentControl. A ContentControl is the base class for controls that contain other elements and have a Content property, e.g. Button.
Then you can override the template to have an AdornerDecorator next to the ContentControl. This is different to what you previously tried as now the ContentPresenter is part of the same visual tree as the Adorner.
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit: Forgot that the AdornerDecorator needs to wrap the container, not just sit side-by-side.

ProgressBar in TabItem Width Issue

Hello dear Stack Overflow users.
I'm experiencing an issue when i place a ProgressBar within the TabControl ItemContainerStyle Template.
The issue only happens if the TabItem headers is stretched to the TabControl width. If there is only few headers, then their width is not changed and the progressbar works fine.
When the ProgressBar value changes the width of the TabItem changes with it from it's current width up to the maximum width possible for a item on that current Tab line. Other tabs on the same header line is either moved or shrinked.
So, two questions:
How do I avoid the headers changes their size to fit the ProgressBar?
Why does the ProgressBar want to be as big as possible?
Visual Example!!
ItemContainerStyle
(All Controls uses stretch as width)
<Style x:Key="TabItemStyle"
TargetType="TabItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Grid ...>
<ProgressBar BorderThickness="0"
Background="{x:Null}"
Value="{Binding Progress}">
<ProgressBar.Style .../>
<ProgressBar.Clip .../>
</ProgressBar>
<Border ...>
<ContentPresenter .../>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
TabControl
<TabControl Name="TabController"
TabStripPlacement="Bottom"
Padding="0"
helpers:TabItemGeneratorBehavior.ItemsSource="{Binding TabPageCollection, Mode=TwoWay}"
helpers:TabItemGeneratorBehavior.SelectedItem="{Binding SelectedTabPage, Mode=TwoWay}"
ItemContainerStyle="{StaticResource TabItemStyle}"/>
Problem fixed! Wraped ProgressBar in a Canvas and set the ProgressBar size to bind to Canvas Actual Width/Height.

WPF fixing fuzzy DataPicker text boxes that have drop shadows

I have a WPF form that has TextBoxes and DatePickers. The DatePicker text boxes fonts are really fuzzy because of a drop shadow effect I put on the style. Initially all the controls had an explicit drop shadow effect as part of the style, but I fixed this by removing the drop shadow effect from the controls and moved it to Rectangles with the same drop shadow.
Then I place the Rectangle directly behind the textboxes - I still have the visual effect and the fonts in the overlaying controls looked great.
<DropShadowEffect x:Key="dropShadow" Color="Gray" Opacity=".50" ShadowDepth="8" />
<Style x:Key="BackingRectangleStyle" TargetType="Rectangle">
<Setter Property="Effect" Value="{StaticResource dropShadow}" />
</Style>
<Rectangle Grid.Row="1" Grid.Column="3" Style="{StaticResource BackingRectangleStyle}"/>
<TextBox Grid.Row="1" Grid.Column="3" ... />
However, I have the same problem with foggy fonts with DatePicker TextBoxes since the drop shadow effect is still directly on the control.
I do not have a DatePicker style, but I do have a style of the DatePickerTextBox, which is where the effect comes from.
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Effect" Value="{StaticResource dropShadow}" />
</Style>
What I don't know how to do is to follow my previous pattern of removing the effect, creating a Rectangle with the same effect and placing it behind the DatePicker TextBox so it's the same size, etc. I need a little help on the XAML to do so.
Can anyone provide me any advice?
Thanks!
Because knowlege about TextFormattingMode really needs spreading, I decided to post the following - even though it strangely doesn't help with the DatePickerTextBox, which is still fuzzy. It prevents you from the stunt you pulled with the rectangle behind the TextBox though.
Unless you have large, or transformed text, always use TextOptions.TextFormattingMode="Display" in your outermost WPF container.
This was introduced in WPF 4.0, and I suppose the default "Ideal" reflects earlier versions, but what a mind-boggling mistake that is...
<Window x:Class="WpfApplication1.MainWindow" x:Name="MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="400"
TextOptions.TextFormattingMode="Display"> <!-- Please notice the effect of this on font fuzzyness -->
<Grid>
<Grid.Resources>
<DropShadowEffect x:Key="DropShadow" Color="Gray" Opacity=".5" ShadowDepth="8"/>
</Grid.Resources>
<TextBox Text="Really Sharp" HorizontalAlignment="Center" Padding="3" VerticalAlignment="Center" Effect="{StaticResource DropShadow}"/>
</Grid>
</Window>

Binding ContentPresenter.Content to TemplatedParent (WPF/Silverlight)

Basically, I would like to overlay, for example: TextBlock over Button, by using ControlTemplate (applied to this Button), but I don't want to get rid of default template of it.
Example:
<Grid Grid.Row="1" Grid.ColumnSpan="2">
<Grid.Resources>
<Style x:Key="myStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<ContentPresenter />
<TextBlock Text="textBlock"
Margin="10" Foreground="Red"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Button Style="{StaticResource myStyle}" Content="button1"></Button>
</Grid>
and it gives Button stripped of it's default template:
Rather, I would like to receive something like this:
Is it possible by using ControlTemplate? I was trying to bind TemplatedParent to ContentPresenter.Content like here:
<ContentPresenter Content="{Binding
RelativeSource={RelativeSource Mode=TemplatedParent},
Path=.,
Mode=TwoWay}"/>
or other combinations, but I couldn't make it work.
Edit:
Because I would like to be able to apply this TextBlock not only to a button (it was just an example) but to any Control, I don't want do it by copying default style (to the resources or somewhere), for every Control.
Also, I would prefer not to create UserControl, because I would like to keep xaml clean as much as possible (I mean with system Controls) - and just to turn on/off the overlaying TextBlock by using a ControlTemplate.
You could add the default style on the button and modify it to add your TextBlock. The second option, my preference, is to create a new UserControl that will contain the Button and the TextBlock with IsHitTestVisible=False. You can then add dependency properties to be able to bind to the button and the text block.

storyboard access element in a control template

I have a usercontrol that contains a custom styled button that I wish to animate.
<UserControl>
<!-- omitted namespaces etc -->
<UserControl.Resources>
<Style x:Key="myButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse x:Name="ellipse" Fill="Orange" />
<es:Arc x:Name="arc" EndAngle="360" Fill="Red" StartAngle="360"/>
</Grid>
</ControlTemplate TargetType="Button">
</Setter.Value>
</Setter>
</Style>
</UserControl.Resouces>
<Grid x:Name="LayoutRoot" />
<Button Tap="Fire_Animation" x:Name="myButton" Style="{StaticResource myButtonStyle}" />
</Grid>
</UserControl>
Once the Button is Tapped, the Fire_Animation method starts a storyboard which is supposed to modify the "Arc" element inside the button's template.
I've seen examples for WPF like this:
// .. previous necessary method calls
StoryBoard.SetTargetName(_myAnimation, "arc");
_storyboard.Begin(myButton, myButton.Template);
But there's no such 'Begin' overload in Windows Phone and as such my storyboard raises an exception that it can't find the 'arc' element. Is there any other workaround?
I would recommend that when you tap the button, that it sets a visual state. You can then provide a storyboard as part of your button template that animates the arc element when the given visual state is applied.

Resources