0

Мне нужно поставить ObservableCollection<ValidationMessage> в мой TextBlock. Вот мой код. Сейчас он показывает Item и SubItems, но там, где сообщения показывают, что он имеет System.Collections.ObjectModel.ObservableCollection'1[ValidationWPF.DataSources.‌​ValidationMessages].Как вы помещаете ObservableCollection в текстовый блок

Я думаю, что это потому, что он не может поставить 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; 

     } 
    } 
} 

Спасибо за вашу помощь !!

ответ

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 КЛАСС:

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 КЛАСС:

public partial class ValidationUserControl : UserControl 
    { 
     public ValidationUserControl() 
     { 
      InitializeComponent(); 
      this.DataContext = new ValidationViewModel(); 

     } 

    } 
2

Вы правы. TextBlock пытается просмотреть значение свойства как String и ObservableCollection.ToString вернет только то, что вы видели.

Что вы можете сделать, это добавить новое свойство, которое объединяет все сообщения ObservableCollection в одну строку. Что-то вроде этого:

public string MessagesCombined 
{ 
    get { return string.Join(Environment.NewLine, Message.Select(m => m.Message)); } 
} 

Это будет объединить все сообщения в вашем ObservableCollection в одну строку, с каждым элементом, разделенных символом новой строки. (Возможно, вам придется немного изменить свой код, я пишу это без доступа к компилятору ...).

+0

Это выглядит, как он может работать.Как я мог затем реализовать это в своем иерархическом шаблоне, чтобы он отображался как Customer Name Message (Это должно происходить как родитель, ребенок, внук) – JLott

3

Проблема в том, что свойство TextTextBlock является строкой, и вы даете ей ObservableCollection. Единственный способ, с помощью которого WPF может преобразовать два, - это вызвать ObservableCollection.ToString(), который возвращает полное имя типа класса.

Исправление состоит в том, чтобы преобразовать ObservableCollection в строку, создав класс, который реализует System.Windows.Data.IValueConverter. Это позволяет вам управлять преобразованием.

Вы могли бы реализовать это что-то вроде этого:

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() всякий раз, когда это необходимо, чтобы заполнить ваш TextBlock ,

+0

Nice! Мне нужно, чтобы мои сообщения отображались в моем HierarchicalDataTemplate, хотя ... Это должны быть Клиенты, Имя, Не может быть Null в порядке Родитель, Ребенок, GrandParent. – JLott

+0

@JLott Это зависит от типа товара. Возможно, вы могли бы сделать что-то подобное и создать для него конвертер значений. – Andy

+0

Остальные элементы - это строка типа. Мне нужно было только преобразовать это. Теперь у меня возникают проблемы с привязкой к DataTemplate, как показано в моем коде выше. – JLott

Смежные вопросы