mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-22 20:37:19 -08:00
Auto scroll when text changed or selection changed in a TextBox
This commit is contained in:
parent
4cb2568385
commit
bd96a9709f
5 changed files with 360 additions and 279 deletions
|
@ -1,143 +1,225 @@
|
|||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace SourceGit.Helpers {
|
||||
|
||||
/// <summary>
|
||||
/// Attached properties to TextBox.
|
||||
/// </summary>
|
||||
public static class TextBoxHelper {
|
||||
|
||||
/// <summary>
|
||||
/// Placeholder property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached(
|
||||
"Placeholder",
|
||||
typeof(string),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(string.Empty, OnPlaceholderChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Vertical alignment for placeholder.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PlaceholderBaselineProperty = DependencyProperty.RegisterAttached(
|
||||
"PlaceholderBaseline",
|
||||
typeof(AlignmentY),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(AlignmentY.Center));
|
||||
|
||||
/// <summary>
|
||||
/// Property to store generated placeholder brush.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PlaceholderBrushProperty = DependencyProperty.RegisterAttached(
|
||||
"PlaceholderBrush",
|
||||
typeof(Brush),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(Brushes.Transparent));
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when placeholder changed.
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnPlaceholderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
||||
var textBox = d as TextBox;
|
||||
if (textBox != null) textBox.Loaded += OnTextLoaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for Placeholder property
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void SetPlaceholder(UIElement element, string value) {
|
||||
element.SetValue(PlaceholderProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getter for Placeholder property
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPlaceholder(UIElement element) {
|
||||
return (string)element.GetValue(PlaceholderProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for PlaceholderBaseline property
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="align"></param>
|
||||
public static void SetPlaceholderBaseline(UIElement element, AlignmentY align) {
|
||||
element.SetValue(PlaceholderBaselineProperty, align);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for PlaceholderBaseline property.
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static AlignmentY GetPlaceholderBaseline(UIElement element) {
|
||||
return (AlignmentY)element.GetValue(PlaceholderBaselineProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for PlaceholderBrush property.
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void SetPlaceholderBrush(UIElement element, Brush value) {
|
||||
element.SetValue(PlaceholderBrushProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getter for PlaceholderBrush property.
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static Brush GetPlaceholderBrush(UIElement element) {
|
||||
return (Brush)element.GetValue(PlaceholderBrushProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set placeholder as background when TextBox was loaded.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnTextLoaded(object sender, RoutedEventArgs e) {
|
||||
var textBox = sender as TextBox;
|
||||
if (textBox == null) return;
|
||||
|
||||
Label placeholder = new Label();
|
||||
placeholder.Content = textBox.GetValue(PlaceholderProperty);
|
||||
|
||||
VisualBrush brush = new VisualBrush();
|
||||
brush.AlignmentX = AlignmentX.Left;
|
||||
brush.AlignmentY = GetPlaceholderBaseline(textBox);
|
||||
brush.TileMode = TileMode.None;
|
||||
brush.Stretch = Stretch.None;
|
||||
brush.Opacity = 0.3;
|
||||
brush.Visual = placeholder;
|
||||
|
||||
textBox.SetValue(PlaceholderBrushProperty, brush);
|
||||
textBox.Background = brush;
|
||||
textBox.TextChanged += OnTextChanged;
|
||||
OnTextChanged(textBox, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dynamically hide/show placeholder.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnTextChanged(object sender, RoutedEventArgs e) {
|
||||
var textBox = sender as TextBox;
|
||||
if (string.IsNullOrEmpty(textBox.Text)) {
|
||||
textBox.Background = textBox.GetValue(PlaceholderBrushProperty) as Brush;
|
||||
} else {
|
||||
textBox.Background = Brushes.Transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace SourceGit.Helpers {
|
||||
|
||||
/// <summary>
|
||||
/// Attached properties to TextBox.
|
||||
/// </summary>
|
||||
public static class TextBoxHelper {
|
||||
|
||||
/// <summary>
|
||||
/// Auto scroll on text changed.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty AutoScrollProperty = DependencyProperty.RegisterAttached(
|
||||
"AutoScroll",
|
||||
typeof(bool),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(false, OnAutoScrollChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Placeholder property
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PlaceholderProperty = DependencyProperty.RegisterAttached(
|
||||
"Placeholder",
|
||||
typeof(string),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(string.Empty, OnPlaceholderChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Vertical alignment for placeholder.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PlaceholderBaselineProperty = DependencyProperty.RegisterAttached(
|
||||
"PlaceholderBaseline",
|
||||
typeof(AlignmentY),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(AlignmentY.Center));
|
||||
|
||||
/// <summary>
|
||||
/// Property to store generated placeholder brush.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PlaceholderBrushProperty = DependencyProperty.RegisterAttached(
|
||||
"PlaceholderBrush",
|
||||
typeof(Brush),
|
||||
typeof(TextBoxHelper),
|
||||
new PropertyMetadata(Brushes.Transparent));
|
||||
|
||||
/// <summary>
|
||||
/// Setter for AutoScrollProperty
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="enabled"></param>
|
||||
public static void SetAutoScroll(UIElement element, bool enabled) {
|
||||
element.SetValue(AutoScrollProperty, enabled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getter for AutoScrollProperty
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static bool GetAutoScroll(UIElement element) {
|
||||
return (bool)element.GetValue(AutoScrollProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when AutoScroll property changed.
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <param name="e"></param>
|
||||
public static void OnAutoScrollChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
||||
var textBox = d as TextBox;
|
||||
if (textBox == null) return;
|
||||
|
||||
textBox.SelectionChanged -= UpdateScrollOnSelectionChanged;
|
||||
if ((bool)e.NewValue == true) {
|
||||
textBox.SelectionChanged += UpdateScrollOnSelectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when placeholder changed.
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnPlaceholderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
||||
var textBox = d as TextBox;
|
||||
if (textBox != null) textBox.Loaded += OnTextLoaded;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for Placeholder property
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void SetPlaceholder(UIElement element, string value) {
|
||||
element.SetValue(PlaceholderProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getter for Placeholder property
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetPlaceholder(UIElement element) {
|
||||
return (string)element.GetValue(PlaceholderProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for PlaceholderBaseline property
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="align"></param>
|
||||
public static void SetPlaceholderBaseline(UIElement element, AlignmentY align) {
|
||||
element.SetValue(PlaceholderBaselineProperty, align);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for PlaceholderBaseline property.
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static AlignmentY GetPlaceholderBaseline(UIElement element) {
|
||||
return (AlignmentY)element.GetValue(PlaceholderBaselineProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setter for PlaceholderBrush property.
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <param name="value"></param>
|
||||
public static void SetPlaceholderBrush(UIElement element, Brush value) {
|
||||
element.SetValue(PlaceholderBrushProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Getter for PlaceholderBrush property.
|
||||
/// </summary>
|
||||
/// <param name="element"></param>
|
||||
/// <returns></returns>
|
||||
public static Brush GetPlaceholderBrush(UIElement element) {
|
||||
return (Brush)element.GetValue(PlaceholderBrushProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set placeholder as background when TextBox was loaded.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void OnTextLoaded(object sender, RoutedEventArgs e) {
|
||||
var textBox = sender as TextBox;
|
||||
if (textBox == null) return;
|
||||
|
||||
Label placeholder = new Label();
|
||||
placeholder.Content = textBox.GetValue(PlaceholderProperty);
|
||||
|
||||
VisualBrush brush = new VisualBrush();
|
||||
brush.AlignmentX = AlignmentX.Left;
|
||||
brush.AlignmentY = GetPlaceholderBaseline(textBox);
|
||||
brush.TileMode = TileMode.None;
|
||||
brush.Stretch = Stretch.None;
|
||||
brush.Opacity = 0.3;
|
||||
brush.Visual = placeholder;
|
||||
|
||||
textBox.SetValue(PlaceholderBrushProperty, brush);
|
||||
textBox.Background = brush;
|
||||
textBox.TextChanged += UpdatePlaceholder;
|
||||
UpdatePlaceholder(textBox, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dynamically hide/show placeholder.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void UpdatePlaceholder(object sender, RoutedEventArgs e) {
|
||||
var textBox = sender as TextBox;
|
||||
if (string.IsNullOrEmpty(textBox.Text)) {
|
||||
textBox.Background = textBox.GetValue(PlaceholderBrushProperty) as Brush;
|
||||
} else {
|
||||
textBox.Background = Brushes.Transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private static void UpdateScrollOnSelectionChanged(object sender, RoutedEventArgs e) {
|
||||
var textBox = sender as TextBox;
|
||||
if (textBox != null && textBox.IsFocused) {
|
||||
if (Mouse.LeftButton == MouseButtonState.Pressed && textBox.SelectionLength > 0) {
|
||||
var p = Mouse.GetPosition(textBox);
|
||||
if (p.X <= 8) {
|
||||
textBox.LineLeft();
|
||||
} else if (p.X >= textBox.ActualWidth - 8) {
|
||||
textBox.LineRight();
|
||||
}
|
||||
|
||||
if (p.Y <= 8) {
|
||||
textBox.LineUp();
|
||||
} else if (p.Y >= textBox.ActualHeight - 8) {
|
||||
textBox.LineDown();
|
||||
}
|
||||
} else {
|
||||
var rect = textBox.GetRectFromCharacterIndex(textBox.CaretIndex);
|
||||
if (rect.Left <= 0) {
|
||||
textBox.ScrollToHorizontalOffset(textBox.HorizontalOffset + rect.Left);
|
||||
} else if (rect.Right >= textBox.ActualWidth) {
|
||||
textBox.ScrollToHorizontalOffset(textBox.HorizontalOffset + rect.Right);
|
||||
}
|
||||
|
||||
if (rect.Top <= 0) {
|
||||
textBox.ScrollToVerticalOffset(textBox.VerticalOffset + rect.Top);
|
||||
} else if (rect.Bottom >= textBox.ActualHeight) {
|
||||
textBox.ScrollToVerticalOffset(textBox.VerticalOffset + rect.Bottom);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,114 +1,118 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- 错误Tooltip -->
|
||||
<ControlTemplate x:Key="Template.Validation.Tooltip" TargetType="{x:Type ToolTip}">
|
||||
<Border x:Name="Root" Margin="5,0,0,0" Opacity="0" Padding="0,0,20,20" RenderTransformOrigin="0,0">
|
||||
<Border.RenderTransform>
|
||||
<TranslateTransform x:Name="xform" X="-25" />
|
||||
</Border.RenderTransform>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="OpenStates">
|
||||
<VisualStateGroup.Transitions>
|
||||
<VisualTransition GeneratedDuration="0" />
|
||||
<VisualTransition GeneratedDuration="0:0:0.2" To="Open">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<BackEase Amplitude=".3" EasingMode="EaseOut" />
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root" />
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
</VisualStateGroup.Transitions>
|
||||
<VisualState x:Name="Closed">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Open">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform" />
|
||||
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<FrameworkElement.Effect>
|
||||
<DropShadowEffect BlurRadius="11" ShadowDepth="6" Opacity="0.4" />
|
||||
</FrameworkElement.Effect>
|
||||
<Border Background="#FFDC000C" BorderThickness="1" BorderBrush="#FFBC000C">
|
||||
<TextBlock Foreground="White" MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{Binding [0].ErrorContent}" UseLayoutRounding="false" />
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
|
||||
<!-- 验证错误模板 -->
|
||||
<ControlTemplate x:Key="Template.Validation.Error">
|
||||
<AdornedElementPlaceholder x:Name="Target">
|
||||
<Border BorderBrush="#FFDB000C" BorderThickness="1" x:Name="root">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="validationTooltip"
|
||||
Placement="Right"
|
||||
PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Template="{StaticResource Template.Validation.Tooltip}"
|
||||
Style="{x:Null}"/>
|
||||
</ToolTipService.ToolTip>
|
||||
<Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Width="12" Margin="1,-4,-4,0" VerticalAlignment="Top">
|
||||
<Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AdornedElementPlaceholder>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding ElementName=Target, Path=AdornedElement.IsKeyboardFocusWithin, Mode=OneWay}" Value="True" />
|
||||
<Condition Binding="{Binding ElementName=Target, Path=AdornedElement.(Validation.HasError), Mode=OneWay}" Value="True" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter TargetName="validationTooltip" Property="IsOpen" Value="True"/>
|
||||
</MultiDataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
|
||||
<!-- 修改默认 -->
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource Brush.FG}"/>
|
||||
<Setter Property="CaretBrush" Value="{DynamicResource Brush.FG}"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border1}"/>
|
||||
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource Template.Validation.Error}"/>
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||
<Border x:Name="Border"
|
||||
Background="{TemplateBinding Background}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}">
|
||||
<ScrollViewer x:Name="PART_ContentHost"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Center"
|
||||
Background="{x:Null}"
|
||||
BorderThickness="0"
|
||||
IsTabStop="False"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource Brush.Accent1}"/>
|
||||
</Trigger>
|
||||
<Trigger Property="AcceptsReturn" Value="True">
|
||||
<Setter TargetName="PART_ContentHost" Property="VerticalAlignment" Value="Top"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:helpers="clr-namespace:SourceGit.Helpers">
|
||||
|
||||
<!-- 错误Tooltip -->
|
||||
<ControlTemplate x:Key="Template.Validation.Tooltip" TargetType="{x:Type ToolTip}">
|
||||
<Border x:Name="Root" Margin="5,0,0,0" Opacity="0" Padding="0,0,20,20" RenderTransformOrigin="0,0">
|
||||
<Border.RenderTransform>
|
||||
<TranslateTransform x:Name="xform" X="-25" />
|
||||
</Border.RenderTransform>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="OpenStates">
|
||||
<VisualStateGroup.Transitions>
|
||||
<VisualTransition GeneratedDuration="0" />
|
||||
<VisualTransition GeneratedDuration="0:0:0.2" To="Open">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0:0:0.2" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform">
|
||||
<DoubleAnimation.EasingFunction>
|
||||
<BackEase Amplitude=".3" EasingMode="EaseOut" />
|
||||
</DoubleAnimation.EasingFunction>
|
||||
</DoubleAnimation>
|
||||
<DoubleAnimation Duration="0:0:0.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root" />
|
||||
</Storyboard>
|
||||
</VisualTransition>
|
||||
</VisualStateGroup.Transitions>
|
||||
<VisualState x:Name="Closed">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Open">
|
||||
<Storyboard>
|
||||
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="X" Storyboard.TargetName="xform" />
|
||||
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="Root" />
|
||||
</Storyboard>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
<FrameworkElement.Effect>
|
||||
<DropShadowEffect BlurRadius="11" ShadowDepth="6" Opacity="0.4" />
|
||||
</FrameworkElement.Effect>
|
||||
<Border Background="#FFDC000C" BorderThickness="1" BorderBrush="#FFBC000C">
|
||||
<TextBlock Foreground="White" MaxWidth="250" Margin="8,4,8,4" TextWrapping="Wrap" Text="{Binding [0].ErrorContent}" UseLayoutRounding="false" />
|
||||
</Border>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
|
||||
<!-- 验证错误模板 -->
|
||||
<ControlTemplate x:Key="Template.Validation.Error">
|
||||
<AdornedElementPlaceholder x:Name="Target">
|
||||
<Border BorderBrush="#FFDB000C" BorderThickness="1" x:Name="root">
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip x:Name="validationTooltip"
|
||||
Placement="Right"
|
||||
PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Template="{StaticResource Template.Validation.Tooltip}"
|
||||
Style="{x:Null}"/>
|
||||
</ToolTipService.ToolTip>
|
||||
<Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Width="12" Margin="1,-4,-4,0" VerticalAlignment="Top">
|
||||
<Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</AdornedElementPlaceholder>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding ElementName=Target, Path=AdornedElement.IsKeyboardFocusWithin, Mode=OneWay}" Value="True" />
|
||||
<Condition Binding="{Binding ElementName=Target, Path=AdornedElement.(Validation.HasError), Mode=OneWay}" Value="True" />
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter TargetName="validationTooltip" Property="IsOpen" Value="True"/>
|
||||
</MultiDataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
|
||||
<!-- 修改默认 -->
|
||||
<Style TargetType="{x:Type TextBox}">
|
||||
<Setter Property="SnapsToDevicePixels" Value="True"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource Brush.FG}"/>
|
||||
<Setter Property="CaretBrush" Value="{DynamicResource Brush.FG}"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border1}"/>
|
||||
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource Template.Validation.Error}"/>
|
||||
<Setter Property="helpers:TextBoxHelper.AutoScroll" Value="True"/>
|
||||
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type TextBox}">
|
||||
<Border x:Name="Border"
|
||||
Background="{TemplateBinding Background}"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}">
|
||||
<ScrollViewer x:Name="PART_ContentHost"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Center"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
IsTabStop="False"
|
||||
CanContentScroll="False"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
|
||||
</Border>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource Brush.Accent1}"/>
|
||||
</Trigger>
|
||||
<Trigger Property="AcceptsReturn" Value="True">
|
||||
<Setter TargetName="PART_ContentHost" Property="VerticalAlignment" Value="Top"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
|
@ -1,18 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net461</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>App.ico</ApplicationIcon>
|
||||
<Company>sourcegit</Company>
|
||||
<Description>OpenSource GIT client for Windows</Description>
|
||||
<Copyright>Copyright © sourcegit 2020. All rights reserved.</Copyright>
|
||||
<ApplicationManifest>App.manifest</ApplicationManifest>
|
||||
<Version>2.0.0-preview</Version>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="App.ico" />
|
||||
</ItemGroup>
|
||||
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net46</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>App.ico</ApplicationIcon>
|
||||
<Company>sourcegit</Company>
|
||||
<Description>OpenSource GIT client for Windows</Description>
|
||||
<Copyright>Copyright © sourcegit 2020. All rights reserved.</Copyright>
|
||||
<ApplicationManifest>App.manifest</ApplicationManifest>
|
||||
<Version>2.0.0-preview</Version>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="App.ico" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -343,8 +343,7 @@
|
|||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
helpers:TextBoxHelper.Placeholder="Enter commit message"
|
||||
helpers:TextBoxHelper.PlaceholderBaseline="Top"
|
||||
TextChanged="CommitMessageChanged">
|
||||
helpers:TextBoxHelper.PlaceholderBaseline="Top">
|
||||
<TextBox.Text>
|
||||
<Binding ElementName="me" Path="CommitMessage" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
|
||||
<Binding.ValidationRules>
|
||||
|
|
|
@ -729,10 +729,6 @@ namespace SourceGit.UI {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CommitMessageChanged(object sender, TextChangedEventArgs e) {
|
||||
(sender as TextBox).ScrollToEnd();
|
||||
}
|
||||
|
||||
private void StartAmend(object sender, RoutedEventArgs e) {
|
||||
var commits = Repo.Commits("-n 1");
|
||||
if (commits.Count == 0) {
|
||||
|
|
Loading…
Reference in a new issue