2014-08-29 5 views
2

Je ne comprends pas le DataTemplate dans ItemTemplate. J'ai une Transcription "StringViewModel" ObservableCollection qui fournit le ItemsSource pour un ItemsControl. Le remplissage de la collection Transcription avec StringViewModel affiche correctement ces chaînes.Comment lier le DataTemplate dans un ItemsControl

Au moment de l'affichage de chaque chaîne, je voudrais que la liaison XAML appelle MyConverter de sorte qu'un code supplémentaire puisse être exécuté sur chaque élément affiché. (Je n'essaie pas de changer ce qui est affiché, mais seulement d'effectuer certaines actions en fonction de la position de ce qui est affiché).

Dans le code suivant, MyConverter n'est jamais appelé. Quelle est la meilleure façon d'appeler MyConverter sur chaque élément présenté dans ItemsControl?

Toute aide est appréciée.

C#

public class StringViewModel : FrameworkElement {...} 

private ObservableCollection<StringViewModel> transcription = new ObservableCollection<StringViewModel>(); 
    public ObservableCollection<StringViewModel> Transcription 
    { 
     get 
     { 
      return transcription; 
     } 
     set 
     { 
      transcription = value; 
     } 
    } 

XAML

<ItemsControl 
       ItemsSource="{Binding Transcription}" 
       > 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <Canvas 
          Background="Transparent" 
          Width="{x:Static h:Constants.widthCanvas}" 
          Height="{x:Static h:Constants.heightCanvas}" 
          /> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate>    <!-- THIS DOES NOT WORK --> 

         <ContentControl Content="{Binding Converter={StaticResource MyConverter}}"/> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 

Ma tentative de changer cela:

<ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <StringViewModel ft="{Binding Path=., Converter={StaticResource MyConverter}}"/> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 

Résultats dans:

ItemTemplate et ItemTemplateSelector sont ignorés pour les éléments déjà du type de conteneur ItemsControl; Type = 'StringViewModel'

Que faire?

Le StringViewModel est défini comme:

public class StringViewModel : FrameworkElement, INotifyPropertyChanged 
{ 

    public StringViewModel() 
    { 
    } 

    public StringViewModel(
     Point topleft, 
     string text, 
     double fontsizediu,       
     SolidColorBrush brush, 
     Func<FormattedText,FormattedText> f,   
     double lineheight) 
    { 
     this.text = text; 
     this.emSize = fontsizediu;     
     this.color = brush; 
     this.topleft = topleft; 
     this.lineheight = lineheight;    
     this.f = f; 
    } 

    protected override void OnRender(DrawingContext dc) 
    { 

     ft = new FormattedText(
      text, 
      CultureInfo.CurrentCulture, 
      FlowDirection.LeftToRight, 
      new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal), 
      emSize, 
      color); 


     ft.TextAlignment = TextAlignment.Left; 

     // apply special styles 
     ft = f(ft); 
     dc.DrawText(ft, topleft); 

    } 

    private string text; 
    private double emSize; 
    private SolidColorBrush color; 
    private Func<FormattedText, FormattedText> f; 

    public Point topleft; 
    private double? Lineheight; 


    private FormattedText _ft; 
    public FormattedText ft 
    { 
     get 
     { 
      return _ft; 
     } 
     set 
     { 
      if (_ft != value) 
      { 
       _ft = value; 
       OnPropertyChanged("ft"); 
      } 
     } 
    } 
+0

Quel est le résultat (effet) voulez-vous réaliser? Vous avez défini ItemsSource pour ItemsControl mais vous n'avez défini aucun élément pour Canvas et ContentControl. – Rang

+0

@Rang Sans la section ItemsControl.ItemTemplate, les chaînes de Transcription s'affichent correctement aux emplacements corrects sur le canevas. En fin de compte, je voudrais utiliser la position de chaque élément affiché pour effectuer des tests visuels dans le convertisseur. La collection Transcription est une collection de type FormattedText qui change dynamiquement. –

+0

vous voulez dire que si vous ajoutez '' le convertisseur n'a jamais été appelé? et avec '', affiche Transcription' dans Canvas correctement? mais j'écris un exemple simple, ça marche. voir ma réponse temporaire. – Rang

Répondre

2

Mise à jour:

conseils Je vous pas effectuer le rendu dans ViewModel, En fait, votre StringViewModel devrait être un StringModel comme ceci: (juste contient certaines propriétés)

public class StringModel : INotifyPropertyChanged 
{ 

    public StringModel() 
    { 
    } 

    public StringModel(
     Point topleft, 
     string text, 
     double fontsizediu, 
     SolidColorBrush brush, 
     double lineheight) 
    { 
     this.text = text; 
     this.emSize = fontsizediu; 
     this.color = brush; 
     this.topleft = topleft; 
     this.lineheight = lineheight; 
    } 


    public string text; 
    public double emSize; 
    public SolidColorBrush color; 

    public Point topleft; 
    public double? lineheight; 


    private FormattedText _ft; 
    public FormattedText ft 
    { 
     get 
     { 
      return _ft; 
     } 
     set 
     { 
      if (_ft != value) 
      { 
       _ft = value; 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

puis, réaliser render convertisseur:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var stringviewmodel = value as StringModel; 
     if (stringviewmodel != null) 
     { 
      stringviewmodel.ft = new FormattedText(
      stringviewmodel.text, 
      CultureInfo.CurrentCulture, 
      FlowDirection.LeftToRight, 
      new Typeface(new FontFamily("Segoe Script"), FontStyles.Italic, FontWeights.Normal, FontStretches.Normal), 
      stringviewmodel.emSize, 
      stringviewmodel.color); 


      stringviewmodel.ft.TextAlignment = TextAlignment.Left; 

      // apply special styles 

      Image myImage = new Image(); 

      DrawingVisual drawingVisual = new DrawingVisual(); 
      DrawingContext dc = drawingVisual.RenderOpen(); 
      dc.DrawText(stringviewmodel.ft, stringviewmodel.topleft); 
      dc.Close(); 

      RenderTargetBitmap bmp = new RenderTargetBitmap(180, 180, 120, 96, PixelFormats.Pbgra32); 
      bmp.Render(drawingVisual); 
      myImage.Source = bmp; 

      return myImage; 
     } 
     else 
     { 
      return null; 
     } 
    } 

ici est le code de itemcontrol:

<ItemsControl x:Name="ic" ItemsSource="{Binding LST}" Margin="0,0,143,185"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel 
         Background="Transparent" 
         /> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <ContentControl Content="{Binding Converter={StaticResource myconverter}}"/> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

et le code principal est:

public partial class MainWindow : Window 
{ 
    private List<StringModel> lst; 

    public List<StringModel> LST 
    { 
     get { return lst; } 
     set { lst = value; } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
     this.DataContext = this; 
     LST = new List<StringModel>(); 

     StringModel vm = new StringModel(new Point(20, 20), "123", 14, Brushes.Red, 2); 
     LST.Add(vm); 

     vm = new StringModel(new Point(20, 20), "456", 16, Brushes.Blue, 3); 
     LST.Add(vm); 

     vm = new StringModel(new Point(20, 20), "789", 18, Brushes.Green, 4); 
     LST.Add(vm); 



    } 
} 

enfin, l'effet de celui-ci:

enter image description here

+0

Excepté pour lier l'ItemsSource directement dans le XAML, j'obtiens "Erreur System.Windows.Data: 26: ItemTemplate et ItemTemplateSelector sont ignorés pour les éléments déjà du type de conteneur ItemsControl; Type = 'StringViewModel'" lorsque en utilisant

+0

@AlanWayne 'StringViewModel' est une classe, peut-être a-t-elle beaucoup de propriétés. Donc, vous ne devriez pas utiliser ContentControl ici. J'ai mis à jour ma réponse. – Rang

+0

Si je fais: < encre: StringViewModel ft = "{Binding Converter = {}} StaticResource HitCheckConverter" /> Je toujours obtenir la System.Windows.Data.Error 26 Que faire ??? –

Questions connexes