2

I'm quite new to WPF, and I'm trying to use a dataGrid. Some of the data I'm trying to display is an image. First I tried to just bind the data like this:

DataGrid.ItemsSource = <some collection>

this resulted with a column containing the path to the Image, not displaying the image.

I started googling around, and I came up with the following:
I created a data template:

<DataTemplate x:Key="ImageDataTemplate">
    <Image Source="{Binding Image}"/>
</DataTemplate>

I added to the AutoGeneratingColumn event a function, and there I put the following code:

if (typeof(System.Windows.Media.ImageSource).IsAssignableFrom(e.PropertyType))
{
    DataGridTemplateColumn dgtc = new DataGridTemplateColumn();
    dgtc.Header = e.Column.Header;
    dgtc.CellTemplate = this.FindResource("ImageDataTemplate") as DataTemplate;

    e.Column = dgtc;
}

witch works fine, as long I call all Image properties in my classes Image is there a way to be a bit more flexible? (I want a few images in a class, or having a meaning full name for the image property, and I don't like almost duplicated code)

4

4 回答 4

0

您可以将数据网格绑定到可观察的集合并像这样构造集合......

public class ViewModel : INotifyPropertyChanged
{
    public ObservableCollection<ImageContainer> MyImageCollection { get; set; }
    public ViewModel()
    {
        MyImageCollection = new ObservableCollection<ImageContainer>();
        MyImageCollection.Add(new ImageContainer{Source = xxx});
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}
public class ImageContainer : INotifyPropertyChanged
{
    private BitmapImage _source;
    public BitmapImage Source
    {
        [DebuggerStepThrough]
        get { return _source; }
        [DebuggerStepThrough]
        set
        {
            if (value != _source)
            {
                _source = value;
                OnPropertyChanged("Source");
            }
        }
    }
    #region INotifyPropertyChanged Implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string name)
    {
        var handler = System.Threading.Interlocked.CompareExchange(ref PropertyChanged, null, null);
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
    #endregion
}

这段代码定义了一个可观察的图像集合和每个图像的绑定容器。如图所示,View Model 构造函数创建了一个集合实例并开始用图像填充它。容器类不必实现INPC,但我不知道你在用图像做什么,所以无论如何都包含 INPC (INotifyPropertyChanged)。

相应的 Xaml 看起来像这样......

    <DataGrid ItemsSource="{Binding MyImageCollection}" AutoGenerateColumns="False" >
        <DataGrid.Columns>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="{Binding Source}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>

如果您从磁盘读取图像,一个流行的变体是绑定到 FileInfo 类并使用转换器返回图像。这种方法使视图模型不那么混乱,但任何一种设计都会提供您正在寻找的东西。

事后思考:如果您仅使用数据网格来显示图像集合,请考虑改用 Items Control。这样做可以避免数据网格的开销。

于 2013-10-11T10:09:17.337 回答
0

这是一个非常具有误导性的标题,因为在您的问题中没有看到“未知”这个词。无论哪种方式,它DataGrid都是一个有点复杂的控件,您似乎是从 WinForms 的角度来看它,通过使用 C# 代码对其进行操作,而不是像 WPF 中的习惯那样简单地定义您希望它在 XAML 中的外观。

我强烈建议您在继续之前阅读一些关于如何以 WPF 方式使用它的教程......那里有很多这样的教程,但是 WPF Tutorials.NET 上的WPF DataGrid Control是一个很好的开始.

简而言之,您可以从链接的教程中定义每列的内容在 XAML 中的样子:

<DataGrid ItemsSource="{Binding Customers}" AutoGenerateColumns="False" >
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Image" Width="SizeToCells" IsReadOnly="True">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Image Source="{Binding Image}" />
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>
于 2013-10-11T09:37:06.053 回答
0

我个人会将AutoGenerateColumnsdatagrid 的属性设置为false,并在 XAML 中手动创建列。

AutoGenerateColumns是不是很有用海事组织。您的模型中经常有您不会在列中显示的属性,如果它最终由AutoGeneratingColumn事件处理程序结束,您将失去不为列显示编写代码的好处。

于 2013-10-11T09:39:45.260 回答
0

也许您可以使用 DataTemplateSelector?

看看这篇文章:http ://tech.pro/tutorial/807/wpf-tutorial-how-to-use-a-datatemplateselector

于 2013-10-11T09:35:48.920 回答