C#将新的Textblock对象绑定到XAML文件中的Textblock控件

问题描述

我想在我的C#-WPF应用程序中显示包含链接的文本。这些文本是静态的,在编译时是已知的。

以下是我直接在XAML文件上工作时想要的东西:

       <TextBlock Name="TextBlockWithHyperlink">
                Some text 
                <Hyperlink 
                    NavigateUri="http://somesite.com"
                    RequestNavigate="Hyperlink_RequestNavigate">
                    some site
                </Hyperlink>
                some more text
      </TextBlock>

由于使用MVVM,我想通过依赖项属性将Textblock绑定到新构造的Textblock对象。 XAML如下所示:

        <StackPanel Grid.Row="1" Margin="5 0 0 0">
            <TextBlock Height="16" FontWeight="Bold" Text="Generic Text with link"/>
          
            <TextBlock Text="{Binding Path=TextWithLink,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>

在我的viewmodel中,放置

private void someMethod(){
   ...
   TextWithLink = CreateText();
   ...
}

private TextBlock(){
   TextBlock tb = new TextBlock();     
   Run run1 = new Run("Text preceeding the hyperlink.");
   Run run2 = new Run("Text following the hyperlink.");
   Run run3 = new Run("Link Text.");

   Hyperlink hyperl = new Hyperlink(run3);
   hyperl.NavigateUri = new Uri("http://search.msn.com");
   

   tb.Inlines.Add(run1);
   tb.Inlines.Add(hyperl);
   tb.Inlines.Add(run2);
   return tb;
}

private TextBlock _textWithLink;
public TextBlock TextWithLink { 
  get => _textWithLink;
  set{
    _textWithLink = value; 
    OnPropertyChanged();
  }
}

依赖项属性设置正在运行,我看到一个新的TextBlock已分配给XAML控件,但是没有显示任何内容,只是显示的文本为

System.Windows.Controls.TextBlock

而不是内容。我无法理解为显示所需的混合文本而必须进行的更改。很高兴获得帮助。

解决方法

与其在视图模型中使用TextBlock实例,不如使用Inline元素的集合以及带有UI元素的UI元素,该元素将其作为绑定的来源。

由于TextBlock的Inlines属性是不可绑定的,因此您可以使用以下可绑定属性来创建带标签的TextBlock:

public class MyTextBlock : TextBlock
{
    public static readonly DependencyProperty BindableInlinesProperty =
        DependencyProperty.Register(
            nameof(BindableInlines),typeof(IEnumerable<Inline>),typeof(MyTextBlock),new PropertyMetadata(null,BindableInlinesPropertyChanged));

    public IEnumerable<Inline> BindableInlines
    {
        get { return (IEnumerable<Inline>)GetValue(BindableInlinesProperty); }
        set { SetValue(BindingGroupProperty,value); }
    }

    private static void BindableInlinesPropertyChanged(
        DependencyObject o,DependencyPropertyChangedEventArgs e)
    {
        var textblock = (MyTextBlock)o;
        var inlines = (IEnumerable<Inline>)e.NewValue;

        textblock.Inlines.Clear();

        if (inlines != null)
        {
            textblock.Inlines.AddRange(inlines);
        }
    }
}

现在您可以像使用它了

<local:MyTextBlock BindableInlines="{Binding SomeInlines}"/>

具有这样的视图模型属性:

public IEnumerable<Inline> SomeInlines { get; set; }

...

var link = new Hyperlink(new Run("Search"));
link.NavigateUri = new Uri("http://search.msn.com");
link.RequestNavigate += (s,e) => Process.Start(e.Uri.ToString());

SomeInlines = new List<Inline>
{
    new Run("Some text "),link,new Run(" and more text")
};

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...