未处理的异常:Xamarin.Forms.Xaml.XamlParseException:位置12:21。找不到关键的FromRTFConverter的StaticResource

时间:2019-01-02 10:38:05

标签: c# xaml xamarin xamarin.forms

我正在尝试以xamarin形式实现Rich Text框。发生此异常。

未处理的异常:Xamarin.Forms.Xaml.XamlParseException:位置12:21。找不到关键的FromRTFConverter的StaticResource

这是我的xaml代码

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:demoapp"
              xmlns:converters="clr-namespace:demoapp"
             x:Class="demoapp.MainPage"
            >


    <StackLayout Orientation="Vertical">

        <Label Text="Simple xamarin forms control" TextColor="Red" HorizontalOptions="Center" FontSize="Large"/>
        <Entry />
        <StackLayout>

            <Picker x:Name="pickerDynamicData" Title="Select Country" HorizontalOptions="FillAndExpand" SelectedItem="{Binding Name}" SelectedIndexChanged="PickerSelection" HeightRequest="50" TextColor="Blue"/>
            <Editor Text="{Binding CaretNote, Mode=OneWay, Converter={StaticResource FromRTFConverter}}" MinimumWidthRequest="250" HorizontalOptions="Fill" VerticalOptions="StartAndExpand"  IsEnabled="False"/>
        </StackLayout>
    </StackLayout>

</ContentPage>

我尝试遵循this的示例来解决此问题。所以我在XAML代码中进行了更改

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:demoapp"
              xmlns:converters="clr-namespace:demoapp"
             x:Class="demoapp.MainPage"
            >

    <ContentPage.Resources>
        <ResourceDictionary>
            <converters:FromRTFConverter x:Key="FromRTFConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout Orientation="Vertical">

        <Label Text="Simple xamarin forms control" TextColor="Red" HorizontalOptions="Center" FontSize="Large"/>
        <Entry />
        <StackLayout>

            <Picker x:Name="pickerDynamicData" Title="Select Country" HorizontalOptions="FillAndExpand" SelectedItem="{Binding Name}" SelectedIndexChanged="PickerSelection" HeightRequest="50" TextColor="Blue"/>
            <Editor Text="{Binding CaretNote, Mode=OneWay, Converter={StaticResource FromRTFConverter}}" MinimumWidthRequest="250" HorizontalOptions="Fill" VerticalOptions="StartAndExpand"  IsEnabled="False"/>
        </StackLayout>
    </StackLayout>

</ContentPage>

但是我得到了这个异常

未找到类型'converters:FromRTFConverter'。确认您没有丢失程序集引用,并且所有引用的程序集均已构建。

这是我的xaml.cs代码

namespace demoapp
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            ObservableCollection<string> objStringList = new ObservableCollection<string>();

            //Mostly below ObservableCollection Items we will get from server but here Iam mentioned static data.
            ObservableCollection<PickerItems> objClassList = new ObservableCollection<PickerItems>();

            objClassList.Add(new PickerItems { Name = "India" });
            objClassList.Add(new PickerItems { Name = "Pakistan" });


            objClassList.Add(new PickerItems { Name = "America" });
            objClassList.Add(new PickerItems { Name = "London" });

            objClassList.Add(new PickerItems { Name = "China" });

            /*Here we have to assign service Items to one ObservableCollection<string>() for this purpose
            I am using foreach and we can add each item to the ObservableCollection<string>(). */

            foreach (var item in objClassList)
            {
                // Here I am adding each item Name to the ObservableCollection<string>() and below I will assign to the Picker
                objStringList.Add(item.Name);
            }

            //Now I am given ItemsSorce to the Pickers
            pickerDynamicData.ItemsSource = objStringList;


        }

        private void PickerSelection(object sender, EventArgs e)
        {
            var picker = (Picker)sender;
            int selectedIndex = picker.SelectedIndex;
            //put your code here
        }

        private void PickerSelection1(object sender, EventArgs e)
        {
            var picker = (Picker)sender;
            int selectedIndex = picker.SelectedIndex;
            //put your code here
        }

    private class StackEntry
    {
        public int NumberOfCharactersToSkip { get; set; }
        public bool Ignorable { get; set; }
        public StackEntry(int numberOfCharactersToSkip, bool ignorable)
        {
            NumberOfCharactersToSkip = numberOfCharactersToSkip;
            Ignorable = ignorable;
        }
    }

    private static readonly Regex _rtfRegex = new Regex(@"\\([a-z]{1,32})(-?\d{1,10})?[ ]?|\\'([0-9a-f]{2})|\\([^a-z])|([{}])|[\r\n]+|(.)", RegexOptions.Singleline | RegexOptions.IgnoreCase);

    /// <summary>
    /// RTF reserved words
    /// </summary>
    private static readonly List<string> destinations = new List<string>
    {
        "aftncn","aftnsep","aftnsepc","annotation","atnauthor","atndate","atnicn","atnid",
        "atnparent","atnref","atntime","atrfend","atrfstart","author","background",
        "bkmkend","bkmkstart","blipuid","buptim","category","colorschememapping",
        "colortbl","comment","company","creatim","datafield","datastore","defchp","defpap",
        "do","doccomm","docvar","dptxbxtext","ebcend","ebcstart","factoidname","falt",
        "fchars","ffdeftext","ffentrymcr","ffexitmcr","ffformat","ffhelptext","ffl",
        "ffname","ffstattext","field","file","filetbl","fldinst","fldrslt","fldtype",
        "fname","fontemb","fontfile","fonttbl","footer","footerf","footerl","footerr",
        "footnote","formfield","ftncn","ftnsep","ftnsepc","g","generator","gridtbl",
        "header","headerf","headerl","headerr","hl","hlfr","hlinkbase","hlloc","hlsrc",
        "hsv","htmltag","info","keycode","keywords","latentstyles","lchars","levelnumbers",
        "leveltext","lfolevel","linkval","list","listlevel","listname","listoverride",
        "listoverridetable","listpicture","liststylename","listtable","listtext",
        "lsdlockedexcept","macc","maccPr","mailmerge","maln","malnScr","manager","margPr",
        "mbar","mbarPr","mbaseJc","mbegChr","mborderBox","mborderBoxPr","mbox","mboxPr",
        "mchr","mcount","mctrlPr","md","mdeg","mdegHide","mden","mdiff","mdPr","me",
        "mendChr","meqArr","meqArrPr","mf","mfName","mfPr","mfunc","mfuncPr","mgroupChr",
        "mgroupChrPr","mgrow","mhideBot","mhideLeft","mhideRight","mhideTop","mhtmltag",
        "mlim","mlimloc","mlimlow","mlimlowPr","mlimupp","mlimuppPr","mm","mmaddfieldname",
        "mmath","mmathPict","mmathPr","mmaxdist","mmc","mmcJc","mmconnectstr",
        "mmconnectstrdata","mmcPr","mmcs","mmdatasource","mmheadersource","mmmailsubject",
        "mmodso","mmodsofilter","mmodsofldmpdata","mmodsomappedname","mmodsoname",
        "mmodsorecipdata","mmodsosort","mmodsosrc","mmodsotable","mmodsoudl",
        "mmodsoudldata","mmodsouniquetag","mmPr","mmquery","mmr","mnary","mnaryPr",
        "mnoBreak","mnum","mobjDist","moMath","moMathPara","moMathParaPr","mopEmu",
        "mphant","mphantPr","mplcHide","mpos","mr","mrad","mradPr","mrPr","msepChr",
        "mshow","mshp","msPre","msPrePr","msSub","msSubPr","msSubSup","msSubSupPr","msSup",
        "msSupPr","mstrikeBLTR","mstrikeH","mstrikeTLBR","mstrikeV","msub","msubHide",
        "msup","msupHide","mtransp","mtype","mvertJc","mvfmf","mvfml","mvtof","mvtol",
        "mzeroAsc","mzeroDesc","mzeroWid","nesttableprops","nextfile","nonesttables",
        "objalias","objclass","objdata","object","objname","objsect","objtime","oldcprops",
        "oldpprops","oldsprops","oldtprops","oleclsid","operator","panose","password",
        "passwordhash","pgp","pgptbl","picprop","pict","pn","pnseclvl","pntext","pntxta",
        "pntxtb","printim","private","propname","protend","protstart","protusertbl","pxe",
        "result","revtbl","revtim","rsidtbl","rxe","shp","shpgrp","shpinst",
        "shppict","shprslt","shptxt","sn","sp","staticval","stylesheet","subject","sv",
        "svb","tc","template","themedata","title","txe","ud","upr","userprops",
        "wgrffmtfilter","windowcaption","writereservation","writereservhash","xe","xform",
        "xmlattrname","xmlattrvalue","xmlclose","xmlname","xmlnstbl",
        "xmlopen"
    };

    /// <summary>
    /// Special characters
    /// </summary>
    private static readonly Dictionary<string, string> specialCharacters = new Dictionary<string, string>
    {
        { "par", "\n" },
        { "sect", "\n\n" },
        { "page", "\n\n" },
        { "line", "\n" },
        { "tab", "\t" },
        { "emdash", "\u2014" },
        { "endash", "\u2013" },
        { "emspace", "\u2003" },
        { "enspace", "\u2002" },
        { "qmspace", "\u2005" },
        { "bullet", "\u2022" },
        { "lquote", "\u2018" },
        { "rquote", "\u2019" },
        { "ldblquote", "\u201C" },
        { "rdblquote", "\u201D" },
    };

    /// <summary>
    /// Strip RTF Tags from RTF Text
    /// </summary>
    /// <param name="inputRtf">RTF formatted text</param>
    /// <returns>Plain text from RTF</returns>
    public static string StripRichTextFormat(string inputRtf)
    {
        if (inputRtf == null)
        {
            return null;
        }

        string returnString;

        var stack = new Stack<StackEntry>();
        bool ignorable = false;              // Whether this group (and all inside it) are "ignorable".
        int ucskip = 1;                      // Number of ASCII characters to skip after a unicode character.
        int curskip = 0;                     // Number of ASCII characters left to skip
        var outList = new List<string>();    // Output buffer.

        MatchCollection matches = _rtfRegex.Matches(inputRtf);

        if (matches.Count > 0)
        {
            foreach (Match match in matches)
            {
                string word = match.Groups[1].Value;
                string arg = match.Groups[2].Value;
                string hex = match.Groups[3].Value;
                string character = match.Groups[4].Value;
                string brace = match.Groups[5].Value;
                string tchar = match.Groups[6].Value;

                if (!String.IsNullOrEmpty(brace))
                {
                    curskip = 0;
                    if (brace == "{")
                    {
                        // Push state
                        stack.Push(new StackEntry(ucskip, ignorable));
                    }
                    else if (brace == "}")
                    {
                        // Pop state
                        StackEntry entry = stack.Pop();
                        ucskip = entry.NumberOfCharactersToSkip;
                        ignorable = entry.Ignorable;
                    }
                }
                else if (!String.IsNullOrEmpty(character)) // \x (not a letter)
                {
                    curskip = 0;
                    if (character == "~")
                    {
                        if (!ignorable)
                        {
                            outList.Add("\xA0");
                        }
                    }
                    else if ("{}\\".Contains(character))
                    {
                        if (!ignorable)
                        {
                            outList.Add(character);
                        }
                    }
                    else if (character == "*")
                    {
                        ignorable = true;
                    }
                }
                else if (!String.IsNullOrEmpty(word)) // \foo
                {
                    curskip = 0;
                    if (destinations.Contains(word))
                    {
                        ignorable = true;
                    }
                    else if (ignorable)
                    {
                    }
                    else if (specialCharacters.ContainsKey(word))
                    {
                        outList.Add(specialCharacters[word]);
                    }
                    else if (word == "uc")
                    {
                        ucskip = Int32.Parse(arg);
                    }
                    else if (word == "u")
                    {
                        int c = Int32.Parse(arg);
                        if (c < 0)
                        {
                            c += 0x10000;
                        }
                        outList.Add(Char.ConvertFromUtf32(c));
                        curskip = ucskip;
                    }
                }
                else if (!String.IsNullOrEmpty(hex)) // \'xx
                {
                    if (curskip > 0)
                    {
                        curskip -= 1;
                    }
                    else if (!ignorable)
                    {
                        int c = Int32.Parse(hex, System.Globalization.NumberStyles.HexNumber);
                        outList.Add(Char.ConvertFromUtf32(c));
                    }
                }
                else if (!String.IsNullOrEmpty(tchar))
                {
                    if (curskip > 0)
                    {
                        curskip -= 1;
                    }
                    else if (!ignorable)
                    {
                        outList.Add(tchar);
                    }
                }
            }
        }
        else
        {
            // Didn't match the regex
            returnString = inputRtf;
        }

        returnString = String.Join(String.Empty, outList.ToArray());

        return returnString;
    }
    public class PickerItems
    {
        public string Name { get; set; }
    }
    }
}

修改

我想我不得不提到FromRTFConverter的类,但是我应该为该类提供什么接口?

还是有一种简单的方法可以在xamarin表单中创建富文本框?

我不知道如何解决此问题。有什么建议么?

1 个答案:

答案 0 :(得分:0)

根据杰拉尔德(Gerald)的评论,假设您的转换器与demoapp位于同一名称空间(不是 demoapp.SubNamespace或其他任何名称),则以下各项应该可以正常工作:

<ContentPage 
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:demoapp"
    xmlns:converters="clr-namespace:demoapp"
    x:Class="demoapp.MainPage">

...

    <Editor 
        Text="{Binding CaretNote, Mode=OneWay, Converter={converters:FromRTFConverter}}"
        ...
        />

...

</ContentPage>