【c#】文本控件
一、TextBlock
1、分行
1.1 若内容超过长度,自动分行
TextWrapping="Wrap"
1.2 自定义分行
//文本内容使用Environment.NewLine进行拼接
this.tb.Text = "第一行内容"+ Environment.NewLine + "第二行内容";
2、截断省略
2.1
TextTrimming="CharacterEllipsis"
2.2 使用时需禁止Wrap,默认为NoWrap
TextWrapping="Wrap"
二、TextBox
1、一些属性
1.1 内容垂直对齐方式,默认为Top
VerticalContentAlignment="Top"//Center,Bottom,Stretch
1.2 最大长度
MaxLength = "";//中文、英文、其他符号都只占一个长度
1.3 文本自动换行
TextWrapping="Wrap"
1.4 Enter换行
AcceptsReturn="True"
2、样式
2.1 普通圆角
<Style TargetType="TextBox" x:Key="ThisTextBoxStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="border" CornerRadius="5" BorderBrush="#CCCCCC" BorderThickness="1" Padding="0,2" Height="{Binding Width, RelativeSource={RelativeSource Self}}" Background="{TemplateBinding Background}">
<ScrollViewer VerticalAlignment="Top" x:Name="PART_ContentHost" DockPanel.Dock="Left" Background="{TemplateBinding Background}" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsReadOnly,RelativeSource={RelativeSource Self}}" Value="true">
<Setter Property="Background" Value="#f0f0f0">
</Setter>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
三、RichTextBox
1、
1.1
四、Placeholder
1、
1.1
五、一些示例
1、TextBoxWithErrorPop 带错误提示框的textBox
1.1 xaml
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="32"></Setter>
<Setter Property="VerticalContentAlignment" Value="Center"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<Border x:Name="border" BorderBrush="#d6d6d6" BorderThickness="1" CornerRadius="5" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
<Grid>
<TextBox x:Name="InTb" AcceptsReturn="True" Margin="4,0" Width="auto" Height="auto" BorderThickness="0" Text="{Binding Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" FontSize="{TemplateBinding FontSize}" Background="{Binding Background,ElementName=border}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" MaxLength="{Binding MaxLength}" Visibility="Visible" TextWrapping="{Binding TextWrapping}"></TextBox>
</Grid>
</Border>
<common:PopupNonTopmost IsOpen="{Binding ErrOpen}" StaysOpen="True" x:Name="Pop_Err"
Placement="Bottom" PlacementTarget="{Binding ElementName=border}"
AllowsTransparency="True" IsTopmost="False" HorizontalAlignment="Left">
<local:ErrorInfoPop Height="32" Width="250" Tag="{TemplateBinding Tag}" ></local:ErrorInfoPop>
</common:PopupNonTopmost>
<!--<Popup AllowsTransparency="True" IsOpen="False" x:Name="Pop_Err">
<local:ErrorInfoPop Height="32" Width="250" Tag="{TemplateBinding Tag}"></local:ErrorInfoPop>
</Popup>-->
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="VerticalContentAlignment" Value="top">
<Setter Property="Margin" TargetName="InTb" Value="4,6"></Setter>
</Trigger>
<DataTrigger Binding="{Binding ErrOpen,RelativeSource={RelativeSource Self}}" Value="false">
<Setter Property="BorderBrush" TargetName="border" Value="#d6d6d6"></Setter>
</DataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsReadOnly,RelativeSource={RelativeSource Self}}" Value="false"></Condition>
<Condition Binding="{Binding IsFocused,RelativeSource={RelativeSource Self}}" Value="true"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="border" Value="#076ff5"></Setter>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsReadOnly,RelativeSource={RelativeSource Self}}" Value="false"></Condition>
<Condition Binding="{Binding IsMouseOver,RelativeSource={RelativeSource Self}}" Value="true"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="BorderBrush" TargetName="border" Value="#076ff5"></Setter>
</MultiDataTrigger>
<DataTrigger Binding="{Binding IsReadOnly,RelativeSource={RelativeSource Self}}" Value="true">
<Setter Property="Background" TargetName="border" Value="#f5f5f5"></Setter>
<Setter Property="BorderBrush" TargetName="border" Value="#d6d6d6"></Setter>
<Setter Property="Foreground" Value="#b3b3b3"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ErrOpen,RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="#ff3939"></Setter>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</TextBox.Style>
1.2 cs
public partial class TextBoxWithErrorPop : TextBox,INotifyPropertyChanged
{
public bool _ErrOpen = false;
public bool ErrOpen { get { return _ErrOpen; } set { _ErrOpen = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ErrOpen")); } }
public ScrollContentPresenter ParentSv;
public Window ParentWin;
public TextBoxWithErrorPop()
{
InitializeComponent();
}
public event PropertyChangedEventHandler PropertyChanged;
public void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
ErrOpen = false;
}
public void TextBox_Loaded(object sender, RoutedEventArgs e)
{
ParentSv = TryGetParent<ScrollContentPresenter>(this);
ParentWin = TryGetParent<Window>(this);
if (ParentSv != null)
{
ParentSv.ScrollOwner.ScrollChanged += (s, ea) =>
{
if (ErrOpen)
{
ErrOpen = false;
}
};
}
if (ParentWin != null)
{
ParentWin.LocationChanged += (s,ea) =>
{
if (ErrOpen)
{
ErrOpen = false;
}
};
}
}
public T TryGetParent<T>(DependencyObject element)
where T : DependencyObject
{
if (element == null)
return null;
DependencyObject parent = VisualTreeHelper.GetParent(element);
if (parent == null)
return null;
T parentTr = parent as T;
if (parentTr != null)
return parentTr;
return TryGetParent<T>(parent);
}
}
1.3 PopupNonTopmost【Topmost = false】
class PopupNonTopmost : Popup
{
/// <summary>
/// Is Topmost dependency property
/// </summary>
public static readonly DependencyProperty IsTopmostProperty = DependencyProperty.Register("IsTopmost", typeof(bool), typeof(PopupNonTopmost), new FrameworkPropertyMetadata(false, OnIsTopmostChanged));
private bool? _appliedTopMost;
private bool _alreadyLoaded;
private Window _parentWindow;
/// <summary>
/// Get/Set IsTopmost
/// </summary>
public bool IsTopmost
{
get { return (bool)GetValue(IsTopmostProperty); }
set { SetValue(IsTopmostProperty, value); }
}
/// <summary>
/// ctor
/// </summary>
public PopupNonTopmost()
{
Loaded += OnPopupLoaded;
Unloaded += OnPopupUnloaded;
}
void OnPopupLoaded(object sender, RoutedEventArgs e)
{
if (_alreadyLoaded)
return;
_alreadyLoaded = true;
if (Child != null)
{
Child.AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(OnChildPreviewMouseLeftButtonDown), true);
}
_parentWindow = Window.GetWindow(this);
if (_parentWindow == null)
return;
_parentWindow.Activated += OnParentWindowActivated;
_parentWindow.Deactivated += OnParentWindowDeactivated;
}
private void OnPopupUnloaded(object sender, RoutedEventArgs e)
{
if (_parentWindow == null)
return;
_parentWindow.Activated -= OnParentWindowActivated;
_parentWindow.Deactivated -= OnParentWindowDeactivated;
}
void OnParentWindowActivated(object sender, EventArgs e)
{
SetTopmostState(true);
}
void OnParentWindowDeactivated(object sender, EventArgs e)
{
if (IsTopmost == false)
{
SetTopmostState(IsTopmost);
}
}
void OnChildPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
SetTopmostState(true);
if (!_parentWindow.IsActive && IsTopmost == false)
{
_parentWindow.Activate();
}
}
private static void OnIsTopmostChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var thisobj = (PopupNonTopmost)obj;
thisobj.SetTopmostState(thisobj.IsTopmost);
}
protected override void OnOpened(EventArgs e)
{
//_appliedTopMost = null;
SetTopmostState(IsTopmost);
base.OnOpened(e);
}
private void SetTopmostState(bool isTop)
{
// Don’t apply state if it’s the same as incoming state
if (_appliedTopMost.HasValue && _appliedTopMost == isTop)
{
return;
}
if (Child == null)
return;
var hwndSource = (PresentationSource.FromVisual(Child)) as HwndSource;
if (hwndSource == null)
return;
var hwnd = hwndSource.Handle;
RECT rect;
if (!GetWindowRect(hwnd, out rect))
return;
if (isTop)
{
SetWindowPos(hwnd, HWND_TOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS);
}
else
{
// Z-Order would only get refreshed/reflected if clicking the
// the titlebar (as opposed to other parts of the external
// window) unless I first set the popup to HWND_BOTTOM
// then HWND_TOP before HWND_NOTOPMOST
SetWindowPos(hwnd, HWND_BOTTOM, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS);
SetWindowPos(hwnd, HWND_TOP, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS);
SetWindowPos(hwnd, HWND_NOTOPMOST, rect.Left, rect.Top, (int)Width, (int)Height, TOPMOST_FLAGS);
}
_appliedTopMost = isTop;
}
#region P/Invoke imports & definitions
#pragma warning disable 1591 //Xml-doc
#pragma warning disable 169 //Never used-warning
// ReSharper disable InconsistentNaming
// Imports etc. with their naming rules
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X,
int Y, int cx, int cy, uint uFlags);
static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
static readonly IntPtr HWND_TOP = new IntPtr(0);
static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
private const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_NOZORDER = 0x0004;
const UInt32 SWP_NOREDRAW = 0x0008;
const UInt32 SWP_NOACTIVATE = 0x0010;
const UInt32 SWP_FRAMECHANGED = 0x0020; /* The frame changed: send WM_NCCALCSIZE */
const UInt32 SWP_SHOWWINDOW = 0x0040;
const UInt32 SWP_HIDEWINDOW = 0x0080;
const UInt32 SWP_NOCOPYBITS = 0x0100;
const UInt32 SWP_NOOWNERZORDER = 0x0200; /* Don’t do owner Z ordering */
const UInt32 SWP_NOSENDCHANGING = 0x0400; /* Don’t send WM_WINDOWPOSCHANGING */
const UInt32 TOPMOST_FLAGS =
SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING;
// ReSharper restore InconsistentNaming
#pragma warning restore 1591
#pragma warning restore 169
#endregion
}
1.4 使用时在cs中ErrOpen = true 即可展示错误info,效果如下;窗口locationChanged 或ScrollChanged时会自动消失