मुझे आंशिक रूप से संपादन योग्य RichTextBox
बनाने के साथ काम सौंपा गया है। मैंने ReadOnly
अनुभागों के लिए TextBlock
तत्वों को जोड़कर Xaml में सुझावों को देखा है, हालांकि इसमें अच्छी तरह से लपेटने का अवांछित दृश्य प्रभाव नहीं है। (यह निरंतर पाठ का एक ब्लॉक के रूप में दिखाई देनी चाहिए।)TextChanged में हटाए जाने से RichTextBox इनलाइन को कैसे रोकें?
मैं एक साथ प्रतिबंधित करने के लिए/कुछ reverse string formatting का उपयोग कर समझौता कर लिया है एक कार्यशील प्रोटोटाइप की अनुमति देने के संपादन और युग्मित प्रयोजनों प्रदर्शित करने के लिए inline Run
elements के गतिशील निर्माण के साथ कि। किसी भी TextChanged
ईवेंट ट्रिगर के अनुसार Run
तत्वों के अनुसार Run
तत्वों को अपडेट करने के लिए एक शब्दकोश का उपयोग करके, इस विचार के साथ कि यदि एक संपादन योग्य सेक्शन का टेक्स्ट पूरी तरह से हटा दिया गया है, तो इसे वापस अपने डिफ़ॉल्ट मान में बदल दिया जाएगा।
स्ट्रिंग में: "हाय NAME, स्पोर्ट शिविर में आपका स्वागत है।", केवल NAME और SPORT संपादन योग्य हैं।
╔═══════╦════════╗ ╔═══════╦════════╗
Default values: ║ Key ║ Value ║ Edited values: ║ Key ║ Value ║
╠═══════╬════════╣ ╠═══════╬════════╣
║ NAME ║ NAME ║ ║ NAME ║ John ║
║ SPORT ║ SPORT ║ ║ SPORT ║ Tennis ║
╚═══════╩════════╝ ╚═══════╩════════╝
"Hi NAME, welcome to SPORT camp." "Hi John, welcome to Tennis camp."
समस्या:
एक विशेष समय में पूरे पाठ मूल्य को हटाया जा रहा RichTextBox Document
से कि रन (और निम्नलिखित रन) को हटा। भले ही मैं उन्हें वापस जोड़ता हूं, फिर भी वे स्क्रीन पर सही ढंग से प्रदर्शित नहीं होते हैं। उदाहरण के लिए, ऊपर सेटअप से संपादित स्ट्रिंग का उपयोग:
उपयोगकर्ता पाठ "जॉन" पर प्रकाश डाला गया और क्लिक हटाएँ, बजाय रिक्त मान बचाने के, इसके बारे में डिफ़ॉल्ट टेक्स्ट के साथ प्रतिस्थापित किया जाना चाहिए "NAME"। आंतरिक रूप से ऐसा होता है। शब्दकोश को सही मान मिलता है,
Run.Text
में मूल्य है,Document
में सभी सहीRun
तत्व शामिल हैं। लेकिन स्क्रीन प्रदर्शित करता है:- अपेक्षित: "हाय NAME, टेनिस शिविर में आपका स्वागत है।"
- वास्तविक: "हाय NAMETennis शिविर।"
Sidenote: इस नुकसान के-रन-तत्व व्यवहार भी जब चिपकाने दोहराया जा सकता है। हाइलाइट करें "स्पोर्ट" और पेस्ट "टेनिस" और रन जिसमें "कैंप" है। खो गया है।
प्रश्न:
कैसे मैं हर Run
तत्व दिखाई भी विनाशकारी कार्यों के माध्यम से, रहते हो एक बार वे प्रतिस्थापित किया गया है?
कोड:
मैं कम से कम उदाहरण के लिए कोड नीचे पट्टी की कोशिश की है, तो मैं निकाल दिया है:
- हर
DependencyProperty
और XAML में बाध्यकारी जुड़े - तर्क recalculating देखभाल की स्थिति (क्षमा करें)
- लिंक किए गए स्ट्रिंग स्वरूपण एक्सटेंशन विधियों को पहले लिंक से दोहराया गया एक विधि में कक्षा के भीतर निहित है। (नोट: यह विधि सरल उदाहरण स्ट्रिंग प्रारूपों के लिए काम करेगी। अधिक मजबूत स्वरूपण के लिए मेरा कोड बहिष्कृत कर दिया गया है। इसलिए कृपया इन परीक्षण उद्देश्यों के लिए प्रदान किए गए उदाहरण से चिपके रहें।)
- संपादन योग्य अनुभाग स्पष्ट रूप से दिखाई देते हैं, रंग योजना को कभी नहीं मानते ।
परीक्षण करने के लिए, कक्षा को अपने WPF प्रोजेक्ट संसाधन फ़ोल्डर में ड्रॉप करें, नामस्थान को ठीक करें, और दृश्य को नियंत्रण जोड़ें।
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
namespace WPFTest.Resources
{
public class MyRichTextBox : RichTextBox
{
public MyRichTextBox()
{
this.TextChanged += MyRichTextBox_TextChanged;
this.Background = Brushes.LightGray;
this.Parameters = new Dictionary<string, string>();
this.Parameters.Add("NAME", "NAME");
this.Parameters.Add("SPORT", "SPORT");
this.Format = "Hi {0}, welcome to {1} camp.";
this.Text = string.Format(this.Format, this.Parameters.Values.ToArray<string>());
this.Runs = new List<Run>()
{
new Run() { Background = Brushes.LightGray, Tag = "Hi " },
new Run() { Background = Brushes.Black, Foreground = Brushes.White, Tag = "NAME" },
new Run() { Background = Brushes.LightGray, Tag = ", welcome to " },
new Run() { Background = Brushes.Black, Foreground = Brushes.White, Tag = "SPORT" },
new Run() { Background = Brushes.LightGray, Tag = " camp." },
};
this.UpdateRuns();
}
public Dictionary<string, string> Parameters { get; set; }
public List<Run> Runs { get; set; }
public string Text { get; set; }
public string Format { get; set; }
private void MyRichTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string richText = new TextRange(this.Document.Blocks.FirstBlock.ContentStart, this.Document.Blocks.FirstBlock.ContentEnd).Text;
string[] oldValues = this.Parameters.Values.ToArray<string>();
string[] newValues = null;
bool extracted = this.TryParseExact(richText, this.Format, out newValues);
if (extracted)
{
var changed = newValues.Select((x, i) => new { NewVal = x, Index = i }).Where(x => x.NewVal != oldValues[x.Index]).FirstOrDefault();
string key = this.Parameters.Keys.ElementAt(changed.Index);
this.Parameters[key] = string.IsNullOrWhiteSpace(newValues[changed.Index]) ? key : newValues[changed.Index];
this.Text = richText;
}
else
{
e.Handled = true;
}
this.UpdateRuns();
}
private void UpdateRuns()
{
this.TextChanged -= this.MyRichTextBox_TextChanged;
foreach (Run run in this.Runs)
{
string value = run.Tag.ToString();
if (this.Parameters.ContainsKey(value))
{
run.Text = this.Parameters[value];
}
else
{
run.Text = value;
}
}
Paragraph p = this.Document.Blocks.FirstBlock as Paragraph;
p.Inlines.Clear();
p.Inlines.AddRange(this.Runs);
this.TextChanged += this.MyRichTextBox_TextChanged;
}
public bool TryParseExact(string data, string format, out string[] values)
{
int tokenCount = 0;
format = Regex.Escape(format).Replace("\\{", "{");
format = string.Format("^{0}$", format);
while (true)
{
string token = string.Format("{{{0}}}", tokenCount);
if (!format.Contains(token))
{
break;
}
format = format.Replace(token, string.Format("(?'group{0}'.*)", tokenCount++));
}
RegexOptions options = RegexOptions.None;
Match match = new Regex(format, options).Match(data);
if (tokenCount != (match.Groups.Count - 1))
{
values = new string[] { };
return false;
}
else
{
values = new string[tokenCount];
for (int index = 0; index < tokenCount; index++)
{
values[index] = match.Groups[string.Format("group{0}", index)].Value;
}
return true;
}
}
}
}
'RichTextBox'' FlowDocument' क्लास के माध्यम से केवल टेक्स्ट एडिटर से कहीं अधिक प्रदान करता है। यह स्वरूपित पाठ, छवियों, तालिकाओं, और यहां तक कि 'UIElements' को प्रदर्शित करने के लिए यह एक आसान नियंत्रण बनाता है। हालांकि ये सभी जटिलता की लागत के साथ आते हैं। इसलिए, 'RichTextBox' से निपटने के बजाय बदसूरत हो सकता है। क्या कोई मौका है कि आप 'एवलॉन एडिट' जैसे अधिक सुविधाजनक नियंत्रण में स्विच कर सकते हैं जो टेक्स्ट प्रोसेसिंग के लिए बेहतर है? –
समस्या से मैं क्या देख सकता हूं कि 'TryParseExact (richText' विफल हो जाता है। क्या इसे ठीक करना शुरू करना उचित है? –
@ qqww2 मैं 'AvalonEdit' से परिचित नहीं हूं या इसकी लाइसेंसिंग आवश्यकताएं हैं, लेकिन मैं इसे मानता हूं। – OhBeWise