C# 这三种清除文本框的方法有什么区别?
我对以下三种清除文本框内容的方法感到困惑。我和WPF一起工作,发现所有的都在工作,但我找不到区别 有人能举例给我解释一下吗C# 这三种清除文本框的方法有什么区别?,c#,wpf,textbox,C#,Wpf,Textbox,我对以下三种清除文本框内容的方法感到困惑。我和WPF一起工作,发现所有的都在工作,但我找不到区别 有人能举例给我解释一下吗 txtUserName.Clear() txtUserName.Text=string.Empty txtUserName.Text=”“ 如果没有深入: 清除:从文本框中删除内容,可能会删除分配给它的资源 public void Clear() { using (this.TextSelectionInternal.DeclareChange
txtUserName.Clear()代码>
txtUserName.Text=string.Empty代码>
txtUserName.Text=”“代码>
public void Clear()
{
using (this.TextSelectionInternal.DeclareChangeBlock())
{
this.TextContainer.DeleteContentInternal(this.TextContainer.Start, this.TextContainer.End);
this.TextSelectionInternal.Select(this.TextContainer.Start, this.TextContainer.Start);
}
}
将空字符串(因为string.empty和“”相等)分配给文本属性只需将空字符串分配给附加属性TextBox.TextProperty:
public string Text
{
get
{
return (string) this.GetValue(TextBox.TextProperty);
}
set
{
this.SetValue(TextBox.TextProperty, (object) value);
}
}
它似乎在做一些额外的工作,比如检查更改的来源、绑定、更新插入符号位置和更新/清除撤消。在分配空字符串时,可能不需要其中的大部分
/// <summary>
/// Callback for changes to the Text property
/// </summary>
private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
TextBox textBox = (TextBox)d;
bool inReentrantChange = false;
int savedCaretIndex = 0;
if (textBox._isInsideTextContentChange)
{
// Ignore property changes that originate from OnTextContainerChanged,
// unless they contain a different value (indicating that a
// re-entrant call changed the value)
if (textBox._newTextValue != DependencyProperty.UnsetValue)
{
// OnTextContainerChanged calls
// SetCurrentDeferredValue(TextProperty, deferredTextReference)
// Usually the DeferredTextReference will appear in the new entry
if (textBox._newTextValue is DeferredTextReference)
{
if (e.NewEntry.IsDeferredReference &&
e.NewEntry.IsCoercedWithCurrentValue &&
e.NewEntry.ModifiedValue.CoercedValue == textBox._newTextValue)
{
return;
}
}
// but if the Text property is data-bound, the deferred reference
// gets converted to a real string; during the conversion (in
// DeferredTextReference.GetValue), the TextBox updates _newTextValue
// to be the string.
else if (e.NewEntry.IsExpression)
{
object newValue = e.NewEntry.IsCoercedWithCurrentValue
? e.NewEntry.ModifiedValue.CoercedValue
: e.NewEntry.ModifiedValue.ExpressionValue;
if (newValue == textBox._newTextValue)
{
return;
}
}
}
// If we get this far, we're being called re-entrantly with a value
// different from the one set by OnTextContainerChanged. We should
// honor this new value.
inReentrantChange = true;
savedCaretIndex = textBox.CaretIndex;
}
// CoerceText will have already converted null -> String.Empty,
// but our default CoerceValueCallback could be overridden by a
// derived class. So check again here.
string newText = (string)e.NewValue;
if (newText == null)
{
newText = String.Empty;
}
textBox._isInsideTextContentChange = true;
try
{
using (textBox.TextSelectionInternal.DeclareChangeBlock())
{
// Update the text content with new TextProperty value.
textBox.TextContainer.DeleteContentInternal((TextPointer)textBox.TextContainer.Start, (TextPointer)textBox.TextContainer.End);
textBox.TextContainer.End.InsertTextInRun(newText);
// Collapse selection to the beginning of a text box
textBox.Select(savedCaretIndex, 0);
}
}
finally
{
//
if (!inReentrantChange)
{
textBox._isInsideTextContentChange = false;
}
}
// We need to clear undo stack in case when the value comes from
// databinding or some other expression.
if (textBox.HasExpression(textBox.LookupEntry(TextBox.TextProperty.GlobalIndex), TextBox.TextProperty))
{
UndoManager undoManager = textBox.TextEditor._GetUndoManager();
if (undoManager != null)
{
if (undoManager.IsEnabled)
undoManager.Clear();
}
}
}
//
///回调以更改文本属性
///
私有静态void OnTextPropertyChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)
{
TextBox TextBox=(TextBox)d;
bool inReentrantChange=false;
int savedCaretIndex=0;
如果(文本框。\u isInsideTextContentChange)
{
//忽略源自OnTextContainerChanged的属性更改,
//除非它们包含不同的值(表示
//重新进入调用(更改了值)
if(textBox.\u newTextValue!=dependencProperty.UnsetValue)
{
//OnTextContainerChanged调用
//SetCurrentDeferredValue(TextProperty,deferredTextReference)
//通常,DelferredTextReference将出现在新条目中
if(textBox.\u newTextValue是延迟的textReference)
{
if(e.NewEntry.IsDeferredReference&&
e、 NewEntry.IsCoercedWithCurrentValue&&
e、 NewEntry.ModifiedValue.ImpressedValue==文本框。\u newTextValue)
{
返回;
}
}
//但是,如果Text属性是数据绑定的,则延迟引用
//转换为实字符串;在转换过程中(在
//DeferredTextReference.GetValue),文本框将更新_newTextValue
//成为一根弦。
else if(如NewEntry.IsExpression)
{
对象newValue=e.NewEntry.IsCoercedWithCurrentValue
?e.NewEntry.ModifiedValue.ImpressedValue
:e.NewEntry.ModifiedValue.ExpressionValue;
如果(newValue==textBox.\u newTextValue)
{
返回;
}
}
}
//如果我们走到这一步,我们将被重新调用,并带有一个值
//与OnTextContainerChanged设置的不同。我们应该
//尊重这一新价值观。
inReentrantChange=真;
savedCaretIndex=textBox.CaretIndex;
}
//强制文本将已转换为null->String.Empty,
//但是我们默认的强制ValueCallback可以被
//派生类。请在此处再次检查。
字符串newText=(字符串)e.NewValue;
if(newText==null)
{
newText=String.Empty;
}
textBox.\u isInsideTextContentChange=true;
尝试
{
使用(textBox.TextSelectionInternal.DeclareChangeBlock())
{
//使用新的TextProperty值更新文本内容。
textBox.TextContainer.DeleteContentInternal((TextPointer)textBox.TextContainer.Start,(TextPointer)textBox.TextContainer.End);
textBox.TextContainer.End.InsertTextInRun(newText);
//将所选内容折叠到文本框的开头
textBox.Select(savedCaretIndex,0);
}
}
最后
{
//
如果(!inReentrantChange)
{
textBox.\u isInsideTextContentChange=false;
}
}
//我们需要清除撤销堆栈,以防值来自
//数据绑定或其他一些表达式。
if(textBox.HasExpression(textBox.LookupEntry(textBox.TextProperty.GlobalIndex),textBox.TextProperty))
{
UndoManager UndoManager=textBox.TextEditor._GetUndoManager();
如果(undoManager!=null)
{
如果(undoManager.IsEnabled)
undoManager.Clear();
}
}
}
清除()方法的作用不仅仅是从文本框中删除文本。它删除所有内容,并重置文本选择和插入符号,正如@syned的答案所示
对于txtUserName.Text=”“代码>示例,如果字符串池中不存在空的字符串
对象,框架将创建一个空的字符串
对象,并将其设置为文本
属性。但是,如果应用程序中已经使用了字符串“
,则框架将使用池中的此值
对于txtUserName.Text=string.Empty例如,框架不会创建空的string
对象,而是引用空字符串常量,并将其设置为Text
属性
在性能测试中,(在文章中)已经表明后两个示例之间确实没有有用的区别。调用Clear()
方法肯定是最慢的,但这显然是因为它除了清除文本外还有其他工作要做。即使如此,这三个选项之间的性能差异实际上仍然不明显。如果您有一些性能差异或内存泄漏,则不会有太多(只是在设置文本而不是使用.Clear()时对事件的一些额外调用)
但是,在使用MVVM时,您无法访问控件本身,因此清除文本的唯一方法是将文本设置为绑定
txtUserName.Clear();
txtUserName.Text = string.Empty;
txtUserName.Text = "";
txtUserName.Clear();
txtUserName.Text = string.Empty;
static String()
{
Empty = "";
}
txtUserName.Text = "";
mscorlib.dll
IL_0007: ldsfld string [mscorlib]System.String::Empty
IL_001a: ldstr ""
txtUserName.Text = "";
txtUserName.Text = string.Empty;
txtUserName.Text = null;
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox Name="txtbx1" Grid.Row="0"/>
<TextBox Name="txtbx2" Grid.Row="1"/>
<TextBox Name="txtbx3" Grid.Row="2"/>
<TextBox Name="txtbx4" Grid.Row="3"/>
</Grid>
using System;
using System.Windows;
namespace WpfApplication4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DateTime oldTime, newTime;
TimeSpan delta;
var iterations = 100000;
#region Test performance 1
oldTime = DateTime.Now;
for (var i = 0; i < iterations; i++)
txtbx1.Text = "";
newTime = DateTime.Now;
delta = newTime - oldTime;
txtbx1.Text = delta.Milliseconds.ToString();
#endregion
#region Test performance 2
oldTime = DateTime.Now;
for (var i = 0; i < iterations; i++)
txtbx2.Text = string.Empty;
newTime = DateTime.Now;
delta = newTime - oldTime;
txtbx2.Text = delta.Milliseconds.ToString();
#endregion
#region Test performance 3
oldTime = DateTime.Now;
for (var i = 0; i < iterations; i++)
txtbx3.Text = null;
newTime = DateTime.Now;
delta = newTime - oldTime;
txtbx3.Text = delta.Milliseconds.ToString();
#endregion
#region Test performance 4
oldTime = DateTime.Now;
for (var i = 0; i < iterations; i++)
txtbx4.Clear();
newTime = DateTime.Now;
delta = newTime - oldTime;
txtbx4.Text = delta.Milliseconds.ToString();
#endregion
}
}
}