如何绘制嵌入在ListView中的Canvas小部件

本文关键字:ListView 中的 Canvas 小部 何绘制 绘制 | 更新日期: 2023-09-27 18:17:00

这是一个非常基本的要求,但我卡住了!WPF/。我只是想动态地绘制到我的ListView的画布列。一次失败尝试:

<ListView name="myGridView">
    <GridViewColumn Header="ColumnA" DisplayMemberBinding="{Binding Path=ColumnA}" />
    <GridViewColumn DisplayMemberBinding="{Binding Path=ColumnB}">
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SUSPECT!
        <Canvas Name="canvasColumn" Width="100" Height="20" />
    </GridViewColumn>
</GridView>

在我的代码中,我有一个类"MyData"与字段绑定到非画布ListView列。我循环一些"Whatever"在ListView中创建项目:

foreach (Whatever whatever in whatevers)
{
    MyData myData = new MyData();
    myData.ColumnA = whatever.A;
    myData.ColumnB = new Canvas();
    Line line = new Line();
    line.Stroke = System.Windows.Media.Brushes.Black;
    line.X1 = line.Y1 = 1;
    line.X2 = line.Y2 = 100;
    line.StrokeThickness = 1;
    myData.ColumnB.Children.Add(line);
    myListView.Items.Add(myData);
}

这行不通:屏幕上画布列的每一行都显示文本"System.Windows.Controls.Canvas"。这并不奇怪—我以与文本列相同的方式绑定了列,并且似乎开始了类型名的toString转换。但是,我已经尝试了一些其他的事情,只是不能得到画布显示。

我还尝试删除上面标记为"嫌疑犯"的列绑定,以及myData的ColumnB字段,寻求一种通过列表视图引用画布小部件的方法,即某种形式:

myListView.reference-to-new-row-and-canvas-column = theNewCanvasIDrewOn;

我的一些搜索已经出现了样式,ItemPanel配置等丑陋的混乱:请-如果这是必要的,我至少希望它可以保持最小....

请多多指教。

欢呼,托尼

<标题> 更新对于我来说,最小的解决方案似乎是在App.xaml的应用程序中添加一个DataTemplate。资源标记:
<DataTemplate x:Key="myTemplate">
    <Canvas Width="60" Height="20" Background="Red" ClipToBounds="True" >
        <ContentPresenter Content="{Binding myCanvasField}" />
    </Canvas>
</DataTemplate>

并将GridViewColumn定义为:

<GridViewColumn CellTemplate="{StaticResource myTemplate}" Header="title" />

感谢Dean为我指出了正确的方向,并为画布特定的细节绑定到画布。然后,我"绘制"我添加到ListView的对象的Canvas属性成员。

如何绘制嵌入在ListView中的Canvas小部件

你需要使用CellTemplate而不是直接使用Canvas

http://msdn.microsoft.com/en-us/library/system.windows.controls.gridviewcolumn.celltemplate.aspx

你可以实现TaskVisualizer作为一个自定义控件,然后在你的列表模板中托管它。这样可以将任务可视化代码与全局UI代码分开。这样做的好处是可以很容易地在其他地方重用任务可视化-例如,当您将鼠标悬停在其他视图中的任务上时,可以很容易地在工具提示中显示相同的图形。

以下是我的看法。其思想是使用迷你DSL在画布和业务对象之间交换信息。

XAML:

<Window x:Class="DrawInCanvas.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DrawInCanvas"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid x:Name="g">
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id" Binding="{Binding Item1}" />
                <DataGridTemplateColumn Header="Bar">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Canvas HorizontalAlignment="Left" 
                                    Height="20"
                                local:CanvasDrawing.Drawing="{Binding Item2}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace DrawInCanvas
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // just a sample
            Dictionary<int, string> barDefinitions = new Dictionary<int, string>(3)
            {
                { 1, "100$red" },
                { 2, "220$yellow" },
                { 3, "40$blue" }
            };
            this.g.ItemsSource =
                Enumerable.Range(1, 3).Select(t => 
                    new Tuple<int, string>(t, barDefinitions[t]));
        }
    }
    public class CanvasDrawing : DependencyObject
    {
        public static readonly DependencyProperty DrawingProperty =
            DependencyProperty.RegisterAttached("Drawing",
                typeof(string),
                typeof(CanvasDrawing),
                new PropertyMetadata(new PropertyChangedCallback((o, e) => 
                {
                    CanvasDrawing.Draw((Canvas)o, (string)e.NewValue);
                })));
        public static void SetDrawing(Canvas canvas, string drawing)
        {
            canvas.SetValue(CanvasDrawing.DrawingProperty, drawing);
        }
        public static string GetDrawing(Canvas canvas)
        {
            return (string)canvas.GetValue(CanvasDrawing.DrawingProperty);
        }
        private static void Draw(Canvas canvas, string drawing)
        {
            string[] parts = drawing.Split("$".ToCharArray());
            canvas.Width = double.Parse(parts[0]);
            canvas.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(parts[1]));
        }
    }
}