[英]C# and Winforms TextBox control: How do I get the text change?
我在我的表單上有一個TextBox.TextChanged事件的事件處理程序。 為了支持撤銷,我想弄清楚TextBox中究竟發生了哪些變化,以便我可以在用戶要求時撤消更改。 (我知道內置文本框支持撤消,但我希望整個應用程序只有一個撤消堆棧)
有合理的方法嗎? 如果沒有,是否有更好的方法來支持這樣的撤消功能?
編輯:像下面的東西似乎工作 - 有什么更好的想法? (現在是這樣的,我真的希望.NET有類似STL的std::mismatch
算法...
class TextModification
{
private string _OldValue;
public string OldValue
{
get
{
return _OldValue;
}
}
private string _NewValue;
public string NewValue
{
get
{
return _NewValue;
}
}
private int _Position;
public int Position
{
get
{
return _Position;
}
}
public TextModification(string oldValue, string newValue, int position)
{
_OldValue = oldValue;
_NewValue = newValue;
_Position = position;
}
public void RevertTextbox(System.Windows.Forms.TextBox tb)
{
tb.Text = tb.Text.Substring(0, Position) + OldValue + tb.Text.Substring(Position + NewValue.Length);
}
}
private Stack<TextModification> changes = new Stack<TextModification>();
private string OldTBText = "";
private bool undoing = false;
private void Undoit()
{
if (changes.Count == 0)
return;
undoing = true;
changes.Pop().RevertTextbox(tbFilter);
OldTBText = tbFilter.Text;
undoing = false;
}
private void UpdateUndoStatus(TextBox caller)
{
int changeStartLocation = 0;
int changeEndTBLocation = caller.Text.Length;
int changeEndOldLocation = OldTBText.Length;
while (changeStartLocation < Math.Min(changeEndOldLocation, changeEndTBLocation) &&
caller.Text[changeStartLocation] == OldTBText[changeStartLocation])
changeStartLocation++;
while (changeEndTBLocation > 1 && changeEndOldLocation > 1 &&
caller.Text[changeEndTBLocation-1] == OldTBText[changeEndOldLocation-1])
{
changeEndTBLocation--;
changeEndOldLocation--;
}
changes.Push(new TextModification(
OldTBText.Substring(changeStartLocation, changeEndOldLocation - changeStartLocation),
caller.Text.Substring(changeStartLocation, changeEndTBLocation - changeStartLocation),
changeStartLocation));
OldTBText = caller.Text;
}
private void tbFilter_TextChanged(object sender, EventArgs e)
{
if (!undoing)
UpdateUndoStatus((TextBox)sender);
}
您可能最好使用Enter和Leave事件。 輸入時,將當前文本存儲在類變量中,然后在離開時將新文本與舊文本進行比較。
是的,不要將其直接綁定到文本框。 你的表單狀態應該在某個模型對象的某個地方,而不是直接與表單綁定(MVC是一種方法,MVVM是另一種方式)。 通過將它們解耦,您可以在更改請求進入時將新文本框值與當前模型值進行比較。
實際上,我能想到的就是擁有一些存儲不同字符串版本的集合(所以你可以多次撤消,而不是只撤消一次)。 我會在TextBox.Tag中存儲對TextBox集合的引用,因此可以直接存儲/使用它。
最后但並非最不重要的是,您在事件TextChange期間更新字符串集合。 沒有太多工作,您可以保持完整的歷史記錄,從您自己的結構中獲取以前的值。
對於你想要完成的事情,這可能有些過分,但CSLA支持n級撤消。 CSLA是由Rocky Lhotka編寫的一個偉大的業務對象框架。 業務對象處理撤消歷史記錄,並通過數據綁定流向UI。
將您的應用切換為使用CSLA將是一項重大承諾,但另一種選擇是查看免費提供的源代碼以了解他是如何實現的。
我實際上正在創建一個自己的語法 - 突出顯示系統,所以我還需要知道更改的文本。 我的解決方案是觀察光標的輸入或空間或沉積。 當WinForms提供Keydown事件時,我使用了KeyEventArguments(e)並將它們轉換為char。
之后我將char存儲到一個字符串中,如:
string i=""; i+=convertedToChar; // convertedToChar = kc.ConvertToString(e.KeyData)
一旦有一個輸入或空間或沉積 - “事件”我刪除字符串。
結果:如果用戶輸入幾個字符並命中空格,我可以讀取最后一個字符(直到最后一個空格)。 一個優點是你可以使用任何分隔符char(只要它們被存儲並由e.KeyCode提供)
但是我希望這是9年后所有人都能看到的解決方案:D。 永遠不會太遲。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.