2014-08-29 109 views
2

我不明白ItemTemplate中的DataTemplate。我有一个为ItemsControl提供ItemsSource的ObservableCollection“StringViewModel”转录。使用StringViewModel填充转录集合正确显示这些字符串。如何绑定ItemsControl中的DataTemplate

在显示每个字符串时,我想让XAML绑定调用MyConverter,以便可以在显示的每个项目上运行附加代码。 (我不是试图改变显示内容,而只是根据显示内容的位置执行一些操作)。

在下面的代码中,MyConverter永远不会被调用。

对ItemsControl中呈现的每个项目调用MyConverter的最佳方式是什么?

任何帮助表示赞赏。

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> 

我试图将其更改为:在

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

结果:

的ItemTemplate和ItemTemplateSelector的物品被忽略ItemsControl的容器类型已经存在; Type ='StringViewModel'

怎么办?

的StringViewModel被定义为:

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

哪个结果(效果)你想实现吗?你已经为ItemsControl设置了ItemsSource,但是你没有为Canvas和ContentControl设置一些东西。 – Rang 2014-08-29 02:01:16

+0

@Rang如果没有ItemsControl.ItemTemplate部分,Transcription中的字符串将正确显示在画布上的正确位置。最终,我想使用每个显示项目的位置来执行转换器内的视觉命中测试。转录集合是一个动态变化的FormattedText类型集合。 – 2014-08-29 02:53:59

+0

你的意思是如果你添加''转换器从来没有被调用?并用''出来,它会在Canvas中正确显示'Transcription'?但我写了一个简单的例子,它的工作原理。看到我的临时答案。 – Rang 2014-08-29 03:13:30

回答

2

更新:

我建议你不要在视图模型实现渲染,其实你StringViewModel应该是这样的一个StringModel:(只包含一些属性)

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; 
} 

,然后实现渲染器:

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; 
     } 
    } 

这里是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> 

和主要代码:

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); 



    } 
} 

最后,它的效果:

enter image description here

+0

除了直接在XAML中绑定ItemsSource,我得到了“System.Windows.Data Error:26:ItemTemplate和ItemTemplateSelector对ItemsControl的容器类型已经存在的项目将被忽略; Type ='StringViewModel'”when使用 2014-08-29 03:44:38

+0

@AlanWayne'StringViewModel'是一个类,可能它有很多属性,所以你不应该在这里使用ContentControl。我已经更新了我的答案。 – Rang 2014-08-29 04:24:50

+0

如果我做的: <墨水:StringViewModel英尺= “{结合转换器= {StaticResource的HitCheckConverter}}”/> 我仍然得到System.Windows.Data.Error 26怎么办? – 2014-08-29 04:46:24

相关问题