带有超链接的 WPF Resources.resx 字符串?

发布于 2024-10-14 18:29:15 字数 865 浏览 1 评论 0原文

我想要一个字符串资源,其中包含一个超链接。我想这是不可能的,除非我有 4 个资源字符串:

预超链接文本 超链接href 超链接文本 超链接后文本。

然后通过以下方式在 xaml 中构造它:

<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right">
    <TextBlock Grid.Column="1" Text="{x:Static p.Resources.PreHText}" />
    <Hyperlink Grid.Column="1" NavigateUri="{x:Static p.Resources.HHref}">
    <TextBlock Text="{x:Static p.Resources.HText}" /></Hyperlink></TextBlock>
    <TextBlock Grid.Column="1" Text="{x:Static p.Resource.PostHText}" />
</StackPanel>

这太糟糕了,原因有很多(样式、不是很动态等)。创建我自己的渲染和字符串格式的栏,例如“请发送电子邮件 {[email protected]< /a>|服务台}以获得进一步帮助”。还有其他方法可以实现这一目标吗? (不必使用 resources.resx 文件)

I want to have a string resource, which contains a hyperlink in it. I guess this isn't possible, unless I had 4 resource strings:

Pre-hyperlink text
hyperlink href
hyperlink text
Post-hyperlink text.

Then construct it in the xaml via:

<StackPanel Grid.Column="1" Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right">
    <TextBlock Grid.Column="1" Text="{x:Static p.Resources.PreHText}" />
    <Hyperlink Grid.Column="1" NavigateUri="{x:Static p.Resources.HHref}">
    <TextBlock Text="{x:Static p.Resources.HText}" /></Hyperlink></TextBlock>
    <TextBlock Grid.Column="1" Text="{x:Static p.Resource.PostHText}" />
</StackPanel>

Which is just awful, for many many reasons (Styling, not very dynamic etc etc). Bar creating my own render and string format, such as "Please email {[email protected]|the helpdesk} for further assistance". Is there any other way to achieve this? (Doesn't have to use the resources.resx file)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七秒鱼° 2024-10-21 18:29:15

最后,我只是为它制作了自己的文本块控件(想象中命名为 AdvancedTextBlock):

    public class AdvancedTextBlock : TextBlock {
        new private String Text { get; set; } //prevent text from being set as overrides all I do here.
        private String _FormattedText = String.Empty;
        public String FormattedText {
            get { return _FormattedText; }
            set { _FormattedText = value; AssignInlines(); }
        }
        private static Regex TagRegex = new Regex(@"\{(?<href>[^\|]+)\|?(?<text>[^}]+)?}", RegexOptions.Compiled);

        public AdvancedTextBlock() : base() { }
        public AdvancedTextBlock(System.Windows.Documents.Inline inline) : base(inline) { }

        public void AssignInlines(){
            this.Inlines.Clear();
            Collection<Hyperlink> hyperlinks = new Collection<Hyperlink>();
            Collection<String> replacements = new Collection<String>();
            MatchCollection mcHrefs = TagRegex.Matches(FormattedText);
            foreach (Match m in mcHrefs) {
                replacements.Add(m.Value);
                Hyperlink hp = new Hyperlink();
                hp.NavigateUri = new Uri(m.Groups["href"].Value);
                hp.Inlines.Add(m.Groups["text"].Success ? m.Groups["text"].Value : m.Groups["href"].Value);
                hp.RequestNavigate += new RequestNavigateEventHandler(hp_RequestNavigate);
                hyperlinks.Add(hp);
            }
            String[] sections = FormattedText.Split(replacements.ToArray(), StringSplitOptions.None);
            hyperlinks.DefaultIfEmpty(null);
            for (int i = 0, l = sections.Length; i < l; i++) {
                this.Inlines.Add(sections.ElementAt(i));
                if (hyperlinks.ElementAtOrDefault(i) != null) {
                    this.Inlines.Add(hyperlinks[i]);
                }
            }
        }

        void hp_RequestNavigate(object sender, RequestNavigateEventArgs e) {
            RequestNavigate(sender, e);
        }

        //
        // Summary:
        //     Occurs when navigation events are requested.
        public event RequestNavigateEventHandler RequestNavigate;
    }

我对我的实现不太满意的唯一两件事是:

A) 我必须隐藏现有的 Text 属性,因为我不知道如何防止该属性覆盖我所做的事情

B) (与 A 相关)我必须调用 每次设置FormattedText字段时(应该只承认一次),但这又是一次,因为不知道如何挂钩到实际执行显示内容的方法(期望找到 PreRender、Render 事件或类似事件,但我找不到),所以如果有人知道如何,那就太棒了:)。

In the end I just made my own textblock control for it (Imaginitively named AdvancedTextBlock):

    public class AdvancedTextBlock : TextBlock {
        new private String Text { get; set; } //prevent text from being set as overrides all I do here.
        private String _FormattedText = String.Empty;
        public String FormattedText {
            get { return _FormattedText; }
            set { _FormattedText = value; AssignInlines(); }
        }
        private static Regex TagRegex = new Regex(@"\{(?<href>[^\|]+)\|?(?<text>[^}]+)?}", RegexOptions.Compiled);

        public AdvancedTextBlock() : base() { }
        public AdvancedTextBlock(System.Windows.Documents.Inline inline) : base(inline) { }

        public void AssignInlines(){
            this.Inlines.Clear();
            Collection<Hyperlink> hyperlinks = new Collection<Hyperlink>();
            Collection<String> replacements = new Collection<String>();
            MatchCollection mcHrefs = TagRegex.Matches(FormattedText);
            foreach (Match m in mcHrefs) {
                replacements.Add(m.Value);
                Hyperlink hp = new Hyperlink();
                hp.NavigateUri = new Uri(m.Groups["href"].Value);
                hp.Inlines.Add(m.Groups["text"].Success ? m.Groups["text"].Value : m.Groups["href"].Value);
                hp.RequestNavigate += new RequestNavigateEventHandler(hp_RequestNavigate);
                hyperlinks.Add(hp);
            }
            String[] sections = FormattedText.Split(replacements.ToArray(), StringSplitOptions.None);
            hyperlinks.DefaultIfEmpty(null);
            for (int i = 0, l = sections.Length; i < l; i++) {
                this.Inlines.Add(sections.ElementAt(i));
                if (hyperlinks.ElementAtOrDefault(i) != null) {
                    this.Inlines.Add(hyperlinks[i]);
                }
            }
        }

        void hp_RequestNavigate(object sender, RequestNavigateEventArgs e) {
            RequestNavigate(sender, e);
        }

        //
        // Summary:
        //     Occurs when navigation events are requested.
        public event RequestNavigateEventHandler RequestNavigate;
    }

The only two things I'm not too happy about with my implementation is that:

A) I had to hack-hide the existing Text property, because I didn't know how to prevent that property from overriding the stuff I do

B) (Related to A) I have to call AssignInlines everytime the FormattedText field is set (which should only be once admittidly), but this is again, down to not knowing how to hook into the method which actually does the displaying stuff (Expecting to find a PreRender, Render event or similar, however I could not), so if anyone knows how to, that'd be awesome :).

给妤﹃绝世温柔 2024-10-21 18:29:15

我的解决方法是在 WPF XAML 顶部声明“x”和“resx”,以便它可以看到资源。 (将 ProductName 替换为产品的命名空间):

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:resx="clr-namespace:ProductName.Properties;assembly=ProductNameResources"

然后我通过使其包含 Run 子控件来调整超链接。 (将 DeactivateCommand 更改为数据上下文中的命令,并将 Strings.Deactivate 更改为您的资源名称。资源属性:

<Hyperlink Command="{Binding DeactivateCommand}" FontSize="18">
   <Run Text="{x:Static resx:Strings.Deactivate}"/>               
</Hyperlink>

我更喜欢这种方式,因为它更短并且没有自定义控件。

如果您需要单词“Contact:”,后跟 emailTo 链接, 你可以:

<TextBlock HorizontalAlignment="Center" FontSize="14">
    <Run Text="{x:Static resx:Strings.Contact}"/>
    <Hyperlink Command="{Binding SupportCommand}" FontStyle="Italic">
       <Run Text="{x:Static resx:Strings.EmailTo}"/>
    </Hyperlink>
</TextBlock> 

My workaround is to declare "x" and "resx" at top of the WPF XAML so it can see the resource. (Replace ProductName with your namespace for the product):

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:resx="clr-namespace:ProductName.Properties;assembly=ProductNameResources"

and then I adjust the hyperlink by having it contain a Run sub control. (Change DeactivateCommand to your command in your data context and the Strings.Deactivate with your resource name.resource property:

<Hyperlink Command="{Binding DeactivateCommand}" FontSize="18">
   <Run Text="{x:Static resx:Strings.Deactivate}"/>               
</Hyperlink>

I prefer this way because it is shorter and no custom control.

If you need the word "Contact:" followed by the emailTo link, you can:

<TextBlock HorizontalAlignment="Center" FontSize="14">
    <Run Text="{x:Static resx:Strings.Contact}"/>
    <Hyperlink Command="{Binding SupportCommand}" FontStyle="Italic">
       <Run Text="{x:Static resx:Strings.EmailTo}"/>
    </Hyperlink>
</TextBlock> 
无悔心 2024-10-21 18:29:15

这是我的解决方案:

<TextBlock x:Name="MyTextBlock" Grid.Column="1" Text="{x:Static resource:ResourceFile.Message}" Style="{StaticResource MyTextStyle}" >
    <Hyperlink>
          click here
    </Hyperlink>
</TextBlock>

Here is my solution:

<TextBlock x:Name="MyTextBlock" Grid.Column="1" Text="{x:Static resource:ResourceFile.Message}" Style="{StaticResource MyTextStyle}" >
    <Hyperlink>
          click here
    </Hyperlink>
</TextBlock>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文