Windows Phone Template and Button - c#

I have an issue with a custom control and its template.
I have a control which extends Button, its template was created via Expression Blend 4 and it is available in ressources of App.xaml.
This is template :
<ControlTemplate x:Key="ImageButtonControlTemplate1" TargetType="maquette_v0__1_Controles_persos:ImageButton">
<Grid Margin="0" Width="150">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled"/>
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image1">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="image1" Source="{TemplateBinding Image}" Height="150"/>
<Image x:Name="image" Source="{TemplateBinding PressedImage}" Height="150"/>
</Grid>
</ControlTemplate>
In a page, I want to add dynamically a custom control.
To do that, I have a grid in my file Xaml "menu_commune" and it is in this grid which I want show my control.
This is the code C# :
ImageButton b = new ImageButton();
b.SetValue(Grid.RowProperty, 0);
b.SetValue(Grid.ColumnProperty, 2);
// bool t = Application.Current.Resources["ImageButtonControlTemplate1"] == null;
ControlTemplate ctemp = (ControlTemplate) Application.Current.Resources["ImageButtonControlTemplate1"];
b.Template = ctemp;
BitmapImage bi_noPress = new BitmapImage(new Uri("/Images/menu_agenda.png"));
BitmapImage bi_Press = new BitmapImage(new Uri("/Images/menu_agenda_selected.png"));
b.Image = bi_noPress;
b.PressedImage = bi_Press;
menu_commune.Children.Add(b);
The problem is nothing is shown.
However, declaration in Xaml runs well.
<UC:ImageButton Grid.Row="2" Grid.Column="2" Image="../Images/menu_office-de-tourisme.png" PressedImage="../Images/menu_office-de-tourisme_selected.png" Height="150" Template="{StaticResource ImageButtonControlTemplate1}" Click="tourisme_Click" />
Thanks

<UC:ImageButton Grid.Row="2" Grid.Column="2" Image="../Images/menu_office-de-tourisme.png" PressedImage="../Images/menu_office-de-tourisme_selected.png" Height="150" Template="{StaticResource ImageButtonControlTemplate1}" Click="tourisme_Click" />
Here you use Grid.Row="2" Grid.Column="2", and in code you need to use same values. Replace
b.SetValue(Grid.RowProperty, 0);
b.SetValue(Grid.ColumnProperty, 2);
for this
b.SetValue(Grid.RowProperty, 2);
b.SetValue(Grid.ColumnProperty, 2);
Hope its help.

Related

WPF States, what is the correct way of setting same property in multiple states

I am trying to style a toggle button and I want the Foreground colour for the selected state and the MouseOver state to be white.
My style is as follows:
<Window.Resources>
<ControlTemplate x:Key="MenuButton" TargetType="{x:Type ToggleButton}">
<Border x:Name="border" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Cursor)" Storyboard.TargetName="MenuItemContainer">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Cursor>Hand</Cursor>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="menuText">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="icon">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
<EasingThicknessKeyFrame KeyTime="0" Value="4,0,0,0"/>
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="#FF19AA8D"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="icon">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="menuText">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="MenuItemContainer" Orientation="Horizontal" Height="46" Margin="14,0,0,0" Background="Transparent" >
<TextBlock x:Name="icon" Grid.Column="0" VerticalAlignment="Center" FontFamily="{StaticResource FontAwesome}" Foreground="#a7b1c2" FontSize="13" Text="" Margin="0,0,6,0"/>
<TextBlock x:Name="menuText" VerticalAlignment="Center" Foreground="#a7b1c2" FontSize="13" Text="{TemplateBinding Property=ContentControl.Content}"/>
</StackPanel>
</Border>
</ControlTemplate>
</Window.Resources>
This is working fine and for MouseOver and Selected states the foreground is set to white. However in Expression Blend Designer I see a warning message which says "To Avoid Unpredictable behaviour, you should not change an object-property in more than one state ..."
Should I just ignore this warning or is there a better way to implement what I am trying to achieve?
Thanks
Yes, you should care about the warning. And in fact the style doesn't behave correctly. Do the following test:
1: set the button to checked -> the text turns to white -> ok
2: move the mouse away -> the text stays in white -> ok
3: move the mouse over the button -> the text stays in white -> ok
4: move the mouse away -> the text turns back to your non-checked default Color -> not ok
In other words you should not modify the same property of the same control from two different visual state groups. Just because the last change wins.
A solution in your case could be this:
<ControlTemplate x:Key="MenuButton" TargetType="{x:Type ToggleButton}">
<Border x:Name="border" >
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Cursor)" Storyboard.TargetName="MenuItemContainer">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Cursor>Hand</Cursor>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Visibility)" Storyboard.TargetName="menuTextMouseOver">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="iconMouseOver">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="menuText">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="icon">
<DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal"/>
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderThickness)" Storyboard.TargetName="border">
<EasingThicknessKeyFrame KeyTime="0" Value="4,0,0,0"/>
</ThicknessAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush)" Storyboard.TargetName="border">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<SolidColorBrush Color="#FF19AA8D"/>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="icon">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="menuText">
<EasingColorKeyFrame KeyTime="0" Value="White"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="MenuItemContainer" Orientation="Horizontal" Height="46" Margin="14,0,0,0" Background="Transparent" >
<TextBlock x:Name="iconMouseOver" Grid.Column="0" VerticalAlignment="Center" Foreground="White" FontSize="13" Text="the icon" Margin="0,0,6,0" Visibility="Collapsed"/>
<TextBlock x:Name="menuTextMouseOver" VerticalAlignment="Center" Foreground="White" FontSize="13" Text="{TemplateBinding Property=ContentControl.Content}" Visibility="Collapsed"/>
<TextBlock x:Name="icon" Grid.Column="0" VerticalAlignment="Center" Foreground="#a7b1c2" FontSize="13" Text="the icon" Margin="0,0,6,0"/>
<TextBlock x:Name="menuText" VerticalAlignment="Center" Foreground="#a7b1c2" FontSize="13" Text="{TemplateBinding Property=ContentControl.Content}"/>
</StackPanel>
</Border>
</ControlTemplate>

From code: Change ScrollViewer's scrollbars'-style to touch

Touch:
Mouse:
How do I tell the ScrollViewer to start using the touch-style scrollbar from code?
Here's an example:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer Name="scrollViewer1" HorizontalScrollBarVisibility="Visible" >
<Image Stretch="UniformToFill">
<Image.Source>
<BitmapImage x:Name="bitmapImage1" UriSource="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png"></BitmapImage>
</Image.Source>
</Image>
</ScrollViewer>
</Grid>
And:
public sealed partial class MainPage : Page
{
DispatcherTimer dispatcherTimer1 = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) };
bool SE;
public MainPage()
{
this.InitializeComponent();
dispatcherTimer1.Tick += DispatcherTimer1_Tick;
dispatcherTimer1.Start();
}
private void DispatcherTimer1_Tick(object sender, object e)
{
if (SE = !SE) bitmapImage1.UriSource = new Uri("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/se/se-icon.png");
else bitmapImage1.UriSource = new Uri("https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-icon.png");
scrollViewer1.ChangeView(SE ? 1 : 0, SE ? 1 : 0, null);
}
}
If you run this (at least on a touch enabled PC) the scrollbars will initially be touch. And if you then move the cursor over it with the mouse, it will change to mouse. and if you then touch it (after the scrollbars have been hidden) it will return to touch.
I want to tell it programmatically to change from one to the other. How can that be done? If the only way is by editing the template - how can that be done without hard coding the template ? Just fixing the detail that needs fixing. To be clear: I want to be able to call a method that will change from one to the other: void ChangeTo(bool mouse) { ... }. (Though, failing that, just forcing the ScrollViewer to always be in one mode, would be somewhat of a workaround.)
Within default template there are 3 VisualStates defined:
NoIndicator,
TouchIndicator and
MouseIndicator
Style of scroller thumb looks different depending on which state is currently set.
To change controls state you can call
VisualStateManager.GoToState(scrollViewer1, "TouchIndicator");
but you would need to manually take care of all events and actions when this state may change.
But if you want to have always TouchIndicator visible then better solution in my opinion would be to implement CustomVisualStateManager, for example:
public class MyVisualStateManager : VisualStateManager
{
protected override bool GoToStateCore(Control control, FrameworkElement templateRoot,
System.String stateName, VisualStateGroup group, VisualState state, System.Boolean useTransitions)
{
switch (stateName)
{
case "NoIndicator":
case "TouchIndicator":
case "MouseIndicator":
base.GoToStateCore(control, templateRoot, "TouchIndicator", group, state, useTransitions);
break;
}
return true;
}
}
Then you need to copy the template from MSDN, set it to your ScrollViewer and put MyVisualStateManager within it:
<Style TargetType="ScrollViewer" x:Key="ScrollStyle">
<Setter Property="HorizontalScrollMode" Value="Auto" />
<Setter Property="VerticalScrollMode" Value="Auto" />
<Setter Property="IsHorizontalRailEnabled" Value="True" />
<Setter Property="IsVerticalRailEnabled" Value="True" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="ZoomMode" Value="Disabled" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Top" />
<Setter Property="VerticalScrollBarVisibility" Value="Visible" />
<Setter Property="Padding" Value="0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.CustomVisualStateManager>
<local:MyVisualStateManager/>
</VisualStateManager.CustomVisualStateManager>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollingIndicatorStates">
<VisualStateGroup.Transitions>
<VisualTransition From="MouseIndicator" To="NoIndicator">
<Storyboard>
(... blabla ...)
</Style>
style set:
<ScrollViewer Name="scrollViewer1" Style="{StaticResource ScrollStyle}" HorizontalScrollBarVisibility="Visible">
Now whenever your ScrollViewer state needs to be changed, you are ignoring what exact state it wants, setting TouchIndicator instead.
Windows has two scroller visualizations, which are based on the user's input mode: scroll indicators when using touch or gamepad; and interactive scroll bars for other input devices including mouse, keyboard, and pen.
And in Guidelines for panning, it is declared that
There are two panning display modes based on the input device detected:
Panning indicators for touch.
Scroll bars for other input devices, including mouse, touchpad, keyboard, and stylus.
Note Panning indicators are only visible when the touch contact is within the pannable region. Similarly, the scroll bar is only visible when the mouse cursor, pen/stylus cursor, or keyboard focus is within the scrollable region.
Panning indicators Panning indicators are similar to the scroll box in a scroll bar. They indicate the proportion of displayed content to total pannable area and the relative position of the displayed content in the pannable area.
Note Unlike standard scroll bars, panning indicators are purely informative. They are not exposed to input devices and cannot be manipulated in any way.
So the display mode is based on user's input mode, we can't programmatically change it from one to the other. What we can do is editing ScrollViewer's template so that ScrollViewer will only use one visualization UI.
In the default style, we can find ScrollViewer has three VisualStates: NoIndicator, TouchIndicator and MouseIndicator, which are used to control the display mode. We can change TouchIndicator or MouseIndicator visual state to make the ScrollViewer always in one display mode.
For example, we can replace the Storyboard under "TouchIndicator" VisualState with the Storyboard under "MouseIndicator" VisualState to make the ScrollViewer always in scroll bar mode like:
<ControlTemplate x:Key="MouseIndicatorTemplate" TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollingIndicatorStates">
<VisualStateGroup.Transitions>
<VisualTransition From="MouseIndicator" To="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation BeginTime="0:0:3" TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:3">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:3">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition From="TouchIndicator" To="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
</Storyboard>
</VisualState>
<VisualState x:Name="TouchIndicator">
<Storyboard>
<FadeInThemeAnimation TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseIndicator">
<Storyboard>
<FadeInThemeAnimation TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>MouseIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="ScrollContentPresenter"
Grid.RowSpan="2"
Grid.ColumnSpan="2"
Margin="{TemplateBinding Padding}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Grid Grid.RowSpan="2" Grid.ColumnSpan="2" />
<ScrollBar x:Name="VerticalScrollBar"
Grid.Column="1"
HorizontalAlignment="Right"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableHeight}"
Orientation="Vertical"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{TemplateBinding VerticalOffset}" />
<ScrollBar x:Name="HorizontalScrollBar"
Grid.Row="1"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableWidth}"
Orientation="Horizontal"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{TemplateBinding HorizontalOffset}" />
<Border x:Name="ScrollBarSeparator"
Grid.Row="1"
Grid.Column="1"
Background="{ThemeResource ScrollViewerScrollBarSeparatorBackground}" />
</Grid>
</Border>
</ControlTemplate>
And vice versa.
<ControlTemplate x:Key="TouchIndicatorTemplate" TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollingIndicatorStates">
<VisualStateGroup.Transitions>
<VisualTransition From="MouseIndicator" To="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation BeginTime="0:0:3" TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:3">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:3">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition From="TouchIndicator" To="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode">
<DiscreteObjectKeyFrame KeyTime="0:0:0.5">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>None</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="NoIndicator">
<Storyboard>
<FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
</Storyboard>
</VisualState>
<VisualState x:Name="TouchIndicator">
<Storyboard>
<FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseIndicator">
<Storyboard>
<FadeOutThemeAnimation TargetName="ScrollBarSeparator" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="IndicatorMode" Duration="0">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<ScrollingIndicatorMode>TouchIndicator</ScrollingIndicatorMode>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ScrollContentPresenter x:Name="ScrollContentPresenter"
Grid.RowSpan="2"
Grid.ColumnSpan="2"
Margin="{TemplateBinding Padding}"
ContentTemplate="{TemplateBinding ContentTemplate}" />
<Grid Grid.RowSpan="2" Grid.ColumnSpan="2" />
<ScrollBar x:Name="VerticalScrollBar"
Grid.Column="1"
HorizontalAlignment="Right"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableHeight}"
Orientation="Vertical"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{TemplateBinding VerticalOffset}" />
<ScrollBar x:Name="HorizontalScrollBar"
Grid.Row="1"
IsTabStop="False"
Maximum="{TemplateBinding ScrollableWidth}"
Orientation="Horizontal"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{TemplateBinding HorizontalOffset}" />
<Border x:Name="ScrollBarSeparator"
Grid.Row="1"
Grid.Column="1"
Background="{ThemeResource ScrollViewerScrollBarSeparatorBackground}" />
</Grid>
</Border>
</ControlTemplate>
Once we have these two templates, we can use ScrollViewer.Template property to change the display mode from one to the other like following ( "MouseIndicatorTemplate" and "TouchIndicatorTemplate" are placed in Page.Resources):
void ChangeTo(bool mouse)
{
if (mouse)
{
scrollViewer1.Template = (ControlTemplate)Resources["MouseIndicatorTemplate"];
}
else
{
scrollViewer1.Template = (ControlTemplate)Resources["TouchIndicatorTemplate"];
}
}
I was looking to restore the simple scrollbar behavior one might expect from a WPF app (removing the touch indicator altogether). The example given by #Jay Zuo didn't work, so I created my own. The templates can be viewed at the following repository:
https://github.com/jsymon/UWP-Classic-ScrollBar-Template

Silverlight button Mouse Over like hover effect

I created button with style but after creating button style it looses default effect of the button and when I directly put attribute in button than I will get those default effects like when I click I can see blue background.I also try to put Visual Manager but it is not working. Kindly somebody can help me to know what I am doing wrong
My Button Style:
<Style TargetType="Button" x:Key="MenuButtonStyle">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="FontFamily" Value="Sitka Heading"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="ButtonTextElement"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
To="Blue"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="normalImage">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="mouseOverImage">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0" Storyboard.TargetName="ButtonTextElement"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
To="Blue"/>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="normalImage">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
Storyboard.TargetName="mouseOverImage">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border BorderBrush="Black" BorderThickness="0,0,0,0.5" Margin="30,0,0,0"
Grid.ColumnSpan="2"/>
<TextBlock x:Name="ButtonTextElement"
Text="{TemplateBinding Content}" Margin="30,0"
Foreground="{TemplateBinding Foreground}" Grid.Column="0"
VerticalAlignment="{TemplateBinding VerticalAlignment}" />
<Image x:Name="normalImage" Source="/Assets/menu-arrow-left.png"
Grid.Column="1" Stretch="None" HorizontalAlignment="Right"
Margin="0,0,30,0" />
<Image x:Name="mouseOverImage" Source="/Assets/menu-arrow-left-hover.png"
Grid.Column="1" Stretch="None" HorizontalAlignment="Right"
Visibility="Collapsed" Margin="0,0,30,0" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I also change in VisualStateManager like this
<ColorAnimation Storyboard.TargetName="MouseOverVisualElement"
Storyboard.TargetProperty="TextBlock.Foreground" To="Red" />
My Button Tag
<Button Style="{StaticResource MenuButtonStyle}" Content="Home"/>
There are several issues with your template. First: You have to make sure that the element identified by Storyboard.TargetName and its property (you want to change) identified by Storyboard.TargetProperty actually make sense. You can change the color of a SolidColorBrush, and you can use a SolidColorBrush for a Textblock.Foreground property, but you cannot directly set the foreground property color, because foreground actually is a Brush (not a Color). Second: if you override the template of a control you have to provide all the VisualStates that are in the original template, that means you have to define the FocusStates as well.
Here is a template that does what you are trying to do:
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation
Duration="0"
Storyboard.TargetName="ButtonTextElement"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
To="Red"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation
Duration="0"
Storyboard.TargetName="Background"
Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)"
To="#FF6DBDD1"/>
<ColorAnimation
Duration="0"
Storyboard.TargetName="ButtonTextElement"
Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)"
To="Red"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation
Duration="0"
Storyboard.TargetName="DisabledVisualElement"
Storyboard.TargetProperty="Opacity"
To=".55"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation
Duration="0"
Storyboard.TargetName="FocusVisualElement"
Storyboard.TargetProperty="Opacity"
To="1"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border
x:Name="Background"
Background="White"/>
<TextBlock
x:Name="ButtonTextElement"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Text="{TemplateBinding Content}"
FontSize="20" FontFamily="Sitka Heading"
Foreground="Black"/>
<Rectangle x:Name="DisabledVisualElement" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" />
<Rectangle x:Name="FocusVisualElement" Margin="1" Stroke="#FF6DBDD1" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" />
</Grid>
</ControlTemplate>
The default button style can be found on msdn.
Please see this page:
https://msdn.microsoft.com/en-us/library/cc278069(VS.95).aspx
and see this page:
http://samples.msdn.microsoft.com/Silverlight/SampleBrowser/index.htm#/?sref=CustomTemplateSamples&id=4
there are a sample for mouse over with templete
Make sure VisualStateManager.VisualStateGroups is the direct child of the root element of your ControlTemplate. In your example, your root element is a Border, so put the VisualStateManager stuff directly under the Border tag.

How to bind a button's normal and pressed background image?

I've managed to save the button style into my AppSetting class based on this code here Cannot correctly populate ListPicker control with Image and Name
Then I want to bind the button's normal and pressed background images (I've several button styles which the user can select in the settings page).
<Style x:Key="ButtonStyle" TargetType="Button">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="Transparent">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="NormalBackground">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PressedBackground">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="NormalBackground">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="PressedBackground">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border x:Name="ButtonBackground" BorderBrush="{x:Null}">
<Grid>
<Image x:Name="NormalBackground" Source="{Binding ButtonUpSetting, Source={StaticResource AppSettings}}" Stretch="Uniform"/>
<Image x:Name="PressedBackground" Source="{Binding ButtonDownSetting, Source={StaticResource AppSettings}}" Stretch="Uniform"/>
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In particular I would like to bind the following items to their respective uri sources but can't perform 'live' binding.
<Image x:Name="NormalBackground" Source="{Binding ButtonUpSetting, Source={StaticResource AppSettings}}" Stretch="Uniform"/>
<Image x:Name="PressedBackground" Source="{Binding ButtonDownSetting, Source={StaticResource AppSettings}}" Stretch="Uniform"/>
I've also implemented INotifyPropertyChangedin my AppSetting class but the button style is not updated when I returned to the button page.
Update:
The button is only updated when I close and reopen the app. So it can read the values from the settings. But it isn't updated right after I change the setting.
The structure of the pages is like the following:
ButtonPage <> SettingPage <> AppSetting Class
So how do I make sure the ButtonPage "re-read" the settings in AppSetting class after I change them in the SettingPage? I am not sure the INotifyPropertyChanged notifies the ButtonPage because it's in the backstack while I make the changes on the SettingPage.
Setting the DataContext = AppSetting inside ButtonPage OnNavigatedTo event does not make any different.
I've figured it out.
Only define the Datacontext in the code not in XAML so
<Image x:Name="NormalBackground" Source="{Binding ButtonUpSetting}" Stretch="Uniform"/>
<Image x:Name="PressedBackground" Source="{Binding ButtonDownSetting}" Stretch="Uniform"/>
Then
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
//Rebind all bindings to update button background images
if (e.NavigationMode == NavigationMode.Back)
{
this.DataContext = null;
this.DataContext = settings;
}
....

Textbox only clickable on "first row"

I have a textbox and which is higher then a "normal" textbox. I am only able to enter text if I click on the "first row" of the textbox. How can I make it possible to click on any part of the textbox and be able to get the cursor shown because this is pretty anoying if you have a 5 line textbox and have to click on the first line to enter some text
<StackPanel Orientation="Vertical" Margin="0,0,15,0">
<TextBlock x:Name="lblObjective" Text="Objective" Style="{StaticResource TextBlockStyle}" VerticalAlignment="Center"></TextBlock>
<TextBox x:Name="Objective" Text="{Binding ObjectiveText, Mode=TwoWay}" TextWrapping="Wrap" Height="120" Width="500"></TextBox>
</StackPanel>
Edit:
This is the template that affects all textboxes in my application. Can anyone say what I need to add to be able to click anywhere on the textbox and still get the caret instead of having to click on the first line
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid x:Name="RootElement">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="FocusRectangle" />
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="DisabledVisualElement">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ReadOnly">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ReadOnlyVisualElement">
<SplineDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="FocusRectangle" />
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="FocusInnerRectangle"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused">
<Storyboard/>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ValidationStates">
<VisualState x:Name="Valid"/>
<VisualState x:Name="InvalidUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="InvalidFocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<sys:Boolean>True</sys:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="Base" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}" Opacity="1" Fill="{StaticResource ControlBackgroundBrush}" />
<Rectangle x:Name="FocusRectangle" StrokeThickness="{TemplateBinding BorderThickness}" Opacity="0" Stroke="{StaticResource TextBoxMouseOverBorderBrush}" />
<Rectangle x:Name="FocusInnerRectangle" StrokeThickness="{TemplateBinding BorderThickness}" Opacity="0" Margin="1" Stroke="{StaticResource TextBoxMouseOverInnerBorderBrush}" />
<Grid Margin="0,1,0,0">
<Border x:Name="ReadOnlyVisualElement" Background="{StaticResource ReadOnlyBrush}" Opacity="0"/>
<Grid >
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Margin="4,0,2,2" VerticalAlignment="Top" Background="{x:Null}"/>
</Grid>
</Grid>
<Rectangle x:Name="DisabledVisualElement" Stroke="{StaticResource ControlsDisabledBrush}" StrokeThickness="{TemplateBinding BorderThickness}" Fill="{StaticResource ControlsDisabledBrush}" IsHitTestVisible="False" Opacity="0"/>
<Border x:Name="ValidationErrorElement" BorderBrush="{StaticResource ControlsValidationBrush}" BorderThickness="1" Visibility="Collapsed">
<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">
<ToolTip.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<sys:Boolean>true</sys:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToolTip.Triggers>
</ToolTip>
</ToolTipService.ToolTip>
<Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
<Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="{StaticResource ValidationBrush5}" Margin="1,3,0,0"/>
<Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="{StaticResource WhiteColorBrush}" Margin="1,3,0,0"/>
</Grid>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
If I remove the whole template everything works fine (i.e. wherever I click on the textbox I get a carret) but then the rest is also lost. So I am missing something any ideas?
Edit 2:
<ScrollViewer x:Name="ContentElement" BorderThickness="0" IsTabStop="False" Margin="4,0,2,2" VerticalAlignment="Top" Background="{x:Null}"/>
was the root of the problem... Instead of having VerticalAlignment="Stretch" it was set to top and therefor only one line was clickable...
I'm not sure what you are seeing but I find that in such a textbox clicking anywhere in the textbox gives it the input focus so I can start editing (regardless BTW of the state of AcceptsReturn although you should have that turned on).
However if the place you click in the box is beyond the end of the current string value the caret is placed at the end of the content not at the place you clicked. This is common text box behaviour, the text box in stackoverflow where I'm typing this has the same behaviour.
If you want to be able to start typing anywhere in the TexBox then you will need to detect the text position of the mousedown and inject the appropriate amount of whitespace. Not a trivial matter.

Categories