首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数据绑定TextBlock.Inlines

数据绑定TextBlock.Inlines
EN

Stack Overflow用户
提问于 2009-12-25 05:51:06
回答 9查看 22.6K关注 0票数 32

我的WPF应用程序从后端服务接收我需要在UI中显示的消息流。这些消息差异很大,我希望有不同的视觉布局(字符串格式,颜色,字体,图标,等等)对于每条消息。

我希望能够为每个消息创建一个内联(运行,TextBlock,斜体等),然后以某种方式将它们都放在一个ObservableCollection<>中,并在UI中使用WPF数据绑定在我的TextBlock.Inlines上的魔力。我不知道怎么做,这是可能的吗?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2009-12-25 08:21:32

这是不可能的,因为TextBlock.Inlines属性不是依赖属性。只有依赖项属性才能成为数据绑定的目标。

根据您的确切布局要求,您可以使用ItemsControl来实现这一点,将其ItemsPanel设置为WrapPanel,将其ItemsSource设置为您的集合。(这里可能需要一些实验,因为Inline不是UIElement,所以它的默认呈现可能会使用ToString()而不是显示。)

或者,您可能需要使用一个可绑定的PartsSource属性和一个TextBlock作为其默认模板来构建一个新控件,例如MultipartTextBlock。设置PartsSource时,您的控件将附加一个CollectionChanged事件处理程序(直接或通过CollectionChangedEventManager),并在PartsSource集合更改时从代码更新TextBlock.Inlines集合。

在这两种情况下,如果您的代码直接生成Inline元素(因为Inline不能在两个地方同时使用),则可能需要小心。您也可以考虑公开文本、字体等的抽象模型(即视图模型),并通过DataTemplate创建实际的Inline对象。这也可能会提高可测试性,但显然会增加复杂性和工作量。

票数 13
EN

Stack Overflow用户

发布于 2012-03-03 21:08:08

您可以向TextBlock子类添加依赖项属性

代码语言:javascript
复制
public class BindableTextBlock : TextBlock
{
    public ObservableCollection<Inline> InlineList
    {
        get { return (ObservableCollection<Inline>)GetValue(InlineListProperty); }
        set { SetValue(InlineListProperty, value); }
    }

    public static readonly DependencyProperty InlineListProperty =
        DependencyProperty.Register("InlineList",typeof(ObservableCollection<Inline>), typeof(BindableTextBlock), new UIPropertyMetadata(null, OnPropertyChanged));

    private static void OnPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        BindableTextBlock textBlock = sender as BindableTextBlock;
        ObservableCollection<Inline> list = e.NewValue as ObservableCollection<Inline>;
        list.CollectionChanged += new     System.Collections.Specialized.NotifyCollectionChangedEventHandler(textBlock.InlineCollectionChanged);
    }

    private void InlineCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
        {
            int idx = e.NewItems.Count -1;
            Inline inline = e.NewItems[idx] as Inline;
            this.Inlines.Add(inline);
        }
    }
}
票数 15
EN

Stack Overflow用户

发布于 2017-12-02 02:54:11

这是另一种利用WPF行为/附加属性的解决方案:

代码语言:javascript
复制
public static class TextBlockExtensions
{
    public static IEnumerable<Inline> GetBindableInlines ( DependencyObject obj )
    {
        return (IEnumerable<Inline>) obj.GetValue ( BindableInlinesProperty );
    }

    public static void SetBindableInlines ( DependencyObject obj, IEnumerable<Inline> value )
    {
        obj.SetValue ( BindableInlinesProperty, value );
    }

    public static readonly DependencyProperty BindableInlinesProperty =
        DependencyProperty.RegisterAttached ( "BindableInlines", typeof ( IEnumerable<Inline> ), typeof ( TextBlockExtensions ), new PropertyMetadata ( null, OnBindableInlinesChanged ) );

    private static void OnBindableInlinesChanged ( DependencyObject d, DependencyPropertyChangedEventArgs e )
    {
        var Target = d as TextBlock;

        if ( Target != null )
        {
            Target.Inlines.Clear ();
            Target.Inlines.AddRange ( (System.Collections.IEnumerable) e.NewValue );
        }
    }
}

在XAML中,像这样使用它:

代码语言:javascript
复制
<TextBlock MyBehaviors:TextBlockExtensions.BindableInlines="{Binding Foo}" />

这使您不必从TextBlock继承。它也可以使用ObservableCollection而不是IEnumerable,在这种情况下,您需要订阅集合更改。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1959856

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档