2014-08-29 104 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

相關問題