C# 如何将ObservableCollection放入文本块

C# 如何将ObservableCollection放入文本块,c#,wpf,xaml,observablecollection,hierarchicaldatatemplate,C#,Wpf,Xaml,Observablecollection,Hierarchicaldatatemplate,我需要将我的ObservableCollection放入我的文本块中。这是我的密码。现在它显示的是项和子项,但消息显示的地方有System.Collections.ObjectModel.ObservableCollection'1[ValidationWPF.DataSources。‌​验证消息] 我认为这是因为它无法将ObservableCollection放入TextBlock XAML: ValidationItem类: using System; using System.Collec

我需要将我的ObservableCollection放入我的文本块中。这是我的密码。现在它显示的是项和子项,但消息显示的地方有System.Collections.ObjectModel.ObservableCollection'1[ValidationWPF.DataSources。‌​验证消息]

我认为这是因为它无法将ObservableCollection放入TextBlock

XAML:

ValidationItem类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace ValidationWPF.DataSources
{
   public class ValidationItem : ObservableCollection<ValidationItem>
    {
        public ValidationItem()
        {
            SubItems = new ObservableCollection<ValidationItem>();


        }


        public ObservableCollection<ValidationMessage> Message
        {
            get;
            set;
        }

        public string item
        {
            get;
            set;
        }

        public IList<ValidationItem> SubItems
        {
            get;
            set;
        }

        public static IList<ValidationItem> GetItems(string name)
        {
            var Validation = new ObservableCollection<ValidationItem>();


            var item = new ValidationItem();
            item.item = "Customer";


            var subItem = new ValidationItem();
            subItem.item = "Name";
            item.SubItems.Add(subItem);

            var Message = new ValidationItem();
            Message.item = new ObservableCollection<ValidationMessage>().ToString();
            subItem.SubItems.Add(Message);






            Validation.Add(item);

            return Validation;

        }
    }
}

谢谢你的帮助

你说得对。TextBlock尝试以字符串形式查看属性值,ObservableCollection.ToString将返回您所看到的内容

您可以做的是添加一个新属性,将ObservableCollection的所有消息组合成一个字符串。大概是这样的:

public string MessagesCombined  
{
   get { return string.Join(Environment.NewLine, Message.Select(m => m.Message)); } 
}
using System.Globalization;
using System.Text;
using System.Windows.Data;

namespace ValidationWPF.DataSources
{
    class CollectionConverter : IValueConverter
    {
        object Convert(object value, Type targetType,object parameter,CultureInfo culture)
        {
            ObservableCollection<ValidationMessage> messages = (ObservableCollection<ValidationMessage>)value;

            var sb = new StringBuilder();
            foreach(var msg in messages)
            {
                sb.AppendLine(msg.Message);
            }

            return sb.ToString();
        }

        object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}
这将把ObservaleCollection中的所有消息组合成一个字符串,每个项用换行符分隔。您可能需要对我的代码进行一些修改,我在编写此代码时没有访问编译器….

问题是TextBlock的Text属性是一个字符串,您给它一个ObservableCollection。WPF知道转换这两者的唯一方法是调用ObservableCollection.ToString,它返回类的完整类型名

修复方法是通过创建实现的类将ObservableCollection转换为字符串。这允许您控制转换

您可以这样实现它:

public string MessagesCombined  
{
   get { return string.Join(Environment.NewLine, Message.Select(m => m.Message)); } 
}
using System.Globalization;
using System.Text;
using System.Windows.Data;

namespace ValidationWPF.DataSources
{
    class CollectionConverter : IValueConverter
    {
        object Convert(object value, Type targetType,object parameter,CultureInfo culture)
        {
            ObservableCollection<ValidationMessage> messages = (ObservableCollection<ValidationMessage>)value;

            var sb = new StringBuilder();
            foreach(var msg in messages)
            {
                sb.AppendLine(msg.Message);
            }

            return sb.ToString();
        }

        object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }
}
您可以在XAML文件中这样使用它:

<UserControl x:Class="ValidationWPF.ValidationUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
             xmlns:local="clr-namespace:ValidationWPF.DataSources"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <local:CollectionConverter x:Key="CollectionConverter" />

        <DataTemplate x:Key="Messages">
            <TextBlock Text="{Binding Message, Converter={StaticResource CollectionConverter}}"/>
        </DataTemplate>
    </UserControl.Resources>
    ...
</UserControl>

现在WPF将调用CollectionConverter.Convert,只要它需要填充您的文本块。

我最终以一种不同且更干净的方式完成了它

XAML:


这看起来是可行的。然后,我如何将其实现到我的HierarchycalDataTemplate中,使其像客户姓名信息一样显示这应该像父、子、孙一样!我需要在我的HierarchycalDataTemplate中显示我的消息,但是。。。它应该是Customers,Name,不能按父、子、祖父母的顺序为空。@JLott,这取决于项目的类型。您可能也可以做类似的事情,并为此创建一个值转换器。其余的项只是字符串类型。我只需要把那个换成。现在我很难让它绑定到上面代码中所示的DataTemplate。@JLott我不熟悉Telerik的控件,但使用标准控件,我希望绑定到主控件上的ItemsSource属性,然后绑定到item模板中该集合项的成员。也许您需要在主控件上设置ItemsSource绑定?此外,在调试时检查输出窗口以查看任何绑定错误。
<UserControl x:Class="ValidationWPF.ValidationUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
             xmlns:local="clr-namespace:ValidationWPF.DataSources"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <UserControl.Resources>
        <!--<local:CollectionConverter x:Key="CollectionConverter"/>
            <DataTemplate x:Key="Messages">
            <TextBlock Text="{Binding Message}"/>
        </DataTemplate>--> 




    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">

        <telerik:RadTreeView x:Name="radTreeView" Margin="8" ItemsSource="{Binding Errors}">
            <telerik:RadTreeView.ItemTemplate>
                 <HierarchicalDataTemplate ItemsSource="{Binding SubItems}" >
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition/>
                            <RowDefinition/>
                        </Grid.RowDefinitions>
                        <TextBlock Text="{Binding Description}"/>

                        <ListBox Grid.Row="1" ItemsSource="{Binding Messages}">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Message}"/>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </Grid>

                </HierarchicalDataTemplate>

            </telerik:RadTreeView.ItemTemplate>
        </telerik:RadTreeView>

    </Grid>
</UserControl>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace ValidationWPF.DataSources
    {
        public class ValidationMessage
        {
            public ValidationMessage(string name, string Message)
            {
                this.Message = Message;
                this.PropertyName = name;
            }

            public string Message
            {
                get;
                set;
            }

            public string PropertyName { get; set; }

        }
    }

VALIDATIONVIEWMODEL CLASS:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Collections.ObjectModel;

    namespace ValidationWPF.DataSources
    {
        public class ValidationViewModel
        {
            public ValidationViewModel()
            {
                this.Errors = new ObservableCollection<ValidationItem>();

                ValidationItem item = new ValidationItem();
                item.Description = "Customer";

                ValidationMessage msg = new ValidationMessage("FirstName", "First name is required");
                item.Messages.Add(msg);


                this.Errors.Add(item);

                ValidationItem item2 = new ValidationItem();
                item2.Description = "Order";

                msg = new ValidationMessage("Quantity", "Quantity must be greater than zero");
                item2.Messages.Add(msg);


                item.SubItems.Add(item2);

            }

            public ObservableCollection<ValidationItem> Errors { get; set; }
        }
    }
  public partial class ValidationUserControl : UserControl
    {
        public ValidationUserControl()
        {
            InitializeComponent();
            this.DataContext = new ValidationViewModel();

        }

    }