Wpf mvvm [continued] sends some QQ expressions, wpfmvvm
Today, the main record is to send QQ expressions, which are written in wpf mvvm. To send QQ expressions later, you need to replace TextBox with RichTextBox. Next, let's talk about the replacement process.
1. RichTextBox supporting Binding
RichTextBox supports text, images, and links, but does not support Binding in native mode. This is inconvenient for MVVM. Therefore, you need to set a dependency attribute Document for RichTextBox, to allow it to support binding.
public class BindableRichTextBox : RichTextBox { public new FlowDocument Document { get { return (FlowDocument)GetValue(DocumentProperty); } set { SetValue(DocumentProperty, value); } } // Using a DependencyProperty as the backing store for Document. This enables animation, styling, binding, etc... public static readonly DependencyProperty DocumentProperty = DependencyProperty.Register("Document", typeof(FlowDocument), typeof(BindableRichTextBox), new FrameworkPropertyMetadata(null,new PropertyChangedCallback(OnDucumentChanged))); private static void OnDucumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RichTextBox rtb = (RichTextBox)d; rtb.Document = (FlowDocument)e.NewValue; } }
BindableRichTextBox 2. emoticons list
The method for listing is written in the blog "Emoji Option List". However, it is modified because it is for doing so.
First, right-click the source file of the web page and you will see the code like this in its emoticons list. Get the content in the title and class from it and create an XML file.
Then, go to the Internet to find the QQ emoticons compressed package. This is not difficult. Then, name the package according to the class, and use the method in the Emoji option list to make the list.
3. Convert String to FlowDocument and FlowDocument to String
For the web version, send a message under F12, and you can see that the sent message is "text + [emoticons]" (the QQ emoticons. Emoji does not see regular expressions now), because, in conversion, there is a goal.
1. Convert FlowDocument to String
Before clicking the send button, we convert the FlowDocument in the send box to a String to send it.
The conversion process is to loop Blocks in FlowDocument (Paragraph is placed in Blocks), then loop Inlines in Paragraph to determine whether the content is InlineUIContainer (Image) or Run (Text)
If it is an image, the Key is obtained from the Dictionary and put in the message to be sent. If it is text, you can simply put it.
Private string GetSendMessage (FlowDocument messages) {if (response = null) {return string. empty;} string resutStr = string. empty; foreach (var root in logs. blocks) {foreach (var item in (Paragraph) root ). inlines) {// if it is Emoji, convert if (item is InlineUIContainer) {System. windows. controls. image img = (System. windows. controls. image) (InlineUIContainer) item ). child; resutStr + = GetEmojiName (img. source. toString ();} // if it is text, assign the value if (item is Run) {resutStr + = (Run) item ). text ;}} return resutStr ;}
Convert FlowDocument to String2 and String to FlowDocument
When receiving a message, the String type is obtained, but the message must be displayed as FlowDocument.
Because we know that the Message format is XXXX [**], we can use a regular expression to intercept the message.
First, determine whether the first character of the string is "[". If yes, extract the content in [] and convert it to Image, then remove [**] From the received string;
If not, use the regular expression to obtain the value before "[" as Text. Then, remove the obtained value from the received string and perform recursion throughout the process, after the string length changes to 0, the system jumps out and adds the obtained content to FlowDocument.
Private void StrToFlDoc (string str, FlowDocument regular, Paragraph par) {// when recursion ends, that is, if (str. length <= 0) {bytes. blocks. add (par); return;} // if the string does not contain [, Add the content if (! Str. contains ('[') {par. inlines. add (new Run (str); str = str. remove (0, str. length); StrToFlDoc (str, substring, par);} else {// set the string Length int strLength = str. length; // first judge whether the first part is [. if yes, it indicates an expression. Use a regular expression to obtain the expression, and then remove the string Length. Recursive if (str [0]. equals ('[') {par. inlines. add (new InlineUIContainer (new System. windows. controls. image {Width = 20, Height = 20, Source = ContantClass. emojiCode [GetEmojiNameByRegex (str)]}); str = str. remove (0, GetEmojiNameByRegex (str ). length); StrToFlDoc (str, delimiter, par);} else {// if the first digit is not [, It is a string and is directly added to the par. inlines. add (new Run (GetTextByRegex (str); str = str. remove (0, GetTextByRegex (str ). length); StrToFlDoc (str, substring, par );}}}
String to FlowDocument
Check the final
Iv. Summary
In the process of replacing Textbox with RichTextBox, many obstacles are encountered, which is not as simple as you thought at the beginning.
For example, when you click on an expression to add it to RichTextbox, you may find that the cursor is not behind the currently added expression, but in front, or after a jump, you have studied it for a long time, I found a solution on the Internet.
Var container = new InlineUIContainer (new Image {Source = EmojiTabControlUC. SelectEmoji. Value, Height = 20, Width = 20}, rtb. CaretPosition );
Rtb. CaretPosition = container. ElementEnd;
Obtain the position of the currently added image, and then redefine the position.
In addition, we can see that the length of RichTextBox in my chat box is equivalent. When TextBox is used, it will change according to the length of the content, and then there is a maximum length. However, I have never found any way to make the length Auto. Please let us know how to do it.
If the code is still GitHub, The address will be included in the post of the wpf mvvm and will not be written here.