c# - 如何在 ItemsControl 中绑定(bind) DataTemplate

标签 c# wpf xaml binding itemscontrol

我不明白 ItemTemplate 中的 DataTemplate。我有一个 ObservableCollection"StringViewModel"转录,它为 ItemsControl 提供 ItemsSource。使用 StringViewModel 填充 Transcription 集合可以正确显示这些字符串。

在显示每个字符串时,我希望 XAML 绑定(bind)调用 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>

结果:

对于已属于 ItemsControl 容器类型的项目,将忽略 ItemTemplate 和 ItemTemplateSelector;类型='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");
            }
        }
    }

最佳答案

更新:

我建议你不要在ViewModel中实现Render,实际上你的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

关于c# - 如何在 ItemsControl 中绑定(bind) DataTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25560594/

相关文章:

wpf - 使用 SQLite 和 Entity Framework 进行数据绑定(bind)

wpf - WPF中超链接中的上标/下标

c# - 不同目标平台中的 Windows 窗体 WebBrowser 控件

c# - 数据传输对象模式

c# - 这个正则表达式是什么意思

xaml - GridView - 在已选择的项目上触发 SelectionChanged 事件

c# - 如何加速 ListBox 渲染和 ListCollectionView 过滤?

c# - 导航期间内存增加,但堆看起来不错?

c# - ComboBox SelectedItem 绑定(bind)

c# - 给定边界矩形、起始角和扫角,如何确定圆弧端点