簡體   English   中英

C#和Winforms TextBox控件:如何更改文本?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM