我需要将ObservableCollection<ValidationMessage>
放入我的TextBlock
。这是我的代码。现在它显示了Item和SubItems,但消息显示它有System.Collections.ObjectModel.ObservableCollection'1[ValidationWPF.DataSources.ValidationMessages]
。
我认为这是因为它无法将ObservableCollection
放入TextBlock
。
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>
<DataTemplate x:Key="Messages">
<TextBlock Text="{Binding Message}"/>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<telerik:RadTreeView x:Name="radTreeView" Margin="8">
<telerik:RadTreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
<TextBlock Text="{Binding item}" />
</HierarchicalDataTemplate>
</telerik:RadTreeView.ItemTemplate>
</telerik:RadTreeView>
</Grid>
</UserControl>
ValidationMessage类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ValidationWPF.DataSources
{
public class ValidationMessage
{
public ValidationMessage(string Message)
{
this.Message = Message;
}
public string Message
{
get;
set;
}
}
}
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;
}
}
}
感谢您的帮助!!
答案 0 :(得分:3)
问题是Text
的{{1}}属性是一个字符串,而你给它TextBlock
。 WPF知道转换两者的唯一方法是调用ObservableCollection
,它返回类的完整类型名称。
修复方法是通过创建实现System.Windows.Data.IValueConverter的类将ObservableCollection.ToString()
转换为字符串。这允许您控制转换。
你可以这样实现:
ObservableCollection
您可以在XAML文件中使用它:
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;
}
}
}
现在,只要需要填充<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()
。
答案 1 :(得分:2)
你是对的。 TextBlock尝试将属性值视为String,而ObservableCollection.ToString将返回您所看到的内容。
您可以做的是添加一个新属性,将ObservableCollection的所有消息组合成一个字符串。像这样:
public string MessagesCombined
{
get { return string.Join(Environment.NewLine, Message.Select(m => m.Message)); }
}
这会将ObservableCollection中的所有消息组合成一个字符串,每个项目用换行符分隔。 (您可能需要稍微修改我的代码,我写这篇文章时无法访问编译器......)。
答案 2 :(得分:2)
我最终采用了另一种更清洁的方式。
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}"/>
</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>
VALIDATIONMESSAGE CLASS:
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; }
}
}
VALIDATIONUSERCONTROL CLASS:
public partial class ValidationUserControl : UserControl
{
public ValidationUserControl()
{
InitializeComponent();
this.DataContext = new ValidationViewModel();
}
}