Необходима помощь в отладке преобразования массива байтов в изображение в WPF datagrid.
Следующий код соответствует требованиям и выполняется, но массив байтов (p_photo) никогда не отображается ни в datagrid, ни в шаблоне details. Когда я помещаю его в отладку, точка останова в конвертере не попадает, поэтому я подозреваю, что проблема заключается в этом. Я не могу определить его, так что любая помощь будет оценена по достоинству.
Что я уже пробовал:
Это мой XAML:
<Window x:Class="SharedUIForms.Person" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:SharedUIForms" mc:Ignorable="d" Title="PersonMaster" Height="450" Width="800" WindowStartupLocation="CenterScreen" WindowState="Maximized"> <Window.Resources> <local:ByteArrayToImageSourceConverter x:Key="ByteArrayToImageSourceConverter" /> </Window.Resources> <Grid ShowGridLines ="True" Background ="LightSteelBlue"> <Grid.Resources> <DataTemplate x:Key="DataTemplate"> <Image Name ="PersonImage" Height="100" Source="{Binding p_photo, Converter={StaticResource ByteArrayToImageSourceConverter}}" /> </DataTemplate> </Grid.Resources> <!-- Define the rows/columns --> <Grid.ColumnDefinitions> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="9*"/> <RowDefinition Height="1*"/> </Grid.RowDefinitions> <!-- Now add the elements to the grid's cells --> <!-- Data grid for the datastore details --> <DataGrid ItemsSource="{Binding Persons}" AlternatingRowBackground="Gainsboro" AlternationCount="2" Grid.Row ="0" AutoGenerateColumns="false"> <DataGrid.Columns> <DataGridTextColumn Header="ID" Binding="{Binding p_PersonID}" /> <DataGridTextColumn Header="Forename" Binding="{Binding p_Forename}" /> <DataGridTextColumn Header="Surname" Binding="{Binding p_Surname}" /> <DataGridTextColumn Header="Address 1" Binding="{Binding p_Address1 }" /> <DataGridTextColumn Header="Address 2" Binding="{Binding p_Address2 }" /> <DataGridTextColumn Header="Address 3" Binding="{Binding p_Address3 }" /> <DataGridTextColumn Header="Address 4" Binding="{Binding p_Address4 }" /> <DataGridTextColumn Header="Email" Binding="{Binding p_Email_Addr}" /> <DataGridTextColumn Header="Mobile Tel" Binding="{Binding p_Mobile_Tel}" /> <DataGridTextColumn Header="Registered" Binding="{Binding p_Registered}" /> <DataGridTextColumn Header="Date Entered" Binding="{Binding p_DateEntered}" /> <!--<DataGridTemplateColumn Header="Picture" CellTemplate="{StaticResource DataTemplate}"/>--> </DataGrid.Columns> <DataGrid.RowDetailsTemplate> <DataTemplate> <Grid ShowGridLines ="True" Background ="LightSteelBlue"> <!-- Define the rows/columns --> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <StackPanel Grid.Column="0"> <Image Name ="PersonImage" Height="100" Source="{Binding p_photo, Converter={StaticResource ByteArrayToImageSourceConverter}}" /> <Button x:Name="btnImage" Width ="80" Content="Add Image" Click="btnImage_Click"/> </StackPanel> <StackPanel Grid.Column="1" Background="LightSteelBlue"> <TextBlock Text="ID: " FontWeight="Bold" /> <TextBlock Text="{Binding p_PersonID}" /> <TextBlock Text="Surname: " FontWeight="Bold" /> <TextBlock Text="{Binding p_Surname}" Grid.Column="1" /> <TextBlock Text="Forename: " FontWeight="Bold" /> <TextBlock Text="{Binding p_Forename}" Grid.Column="1" /> <TextBlock Text="Email: " FontWeight="Bold" /> <TextBlock Text="{Binding p_Email_Addr}" Grid.Column="1" /> <TextBlock Text="Moblile Telepone: " FontWeight="Bold" /> <TextBlock Text="{Binding p_Mobile_Tel}" Grid.Column="1" /> <TextBlock Text=" " FontWeight="Bold" /> </StackPanel> <StackPanel Grid.Column="2"></StackPanel> <StackPanel Grid.Column="3"></StackPanel> </Grid> </DataTemplate> </DataGrid.RowDetailsTemplate> </DataGrid> <!-- Button grid for the controls --> <Grid ShowGridLines ="True" Background ="LightCyan" Grid.Row ="1"> <!-- Define the rows/columns --> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> </Grid.RowDefinitions> <Button x:Name="btnCommit" Height ="30" Width="100" Grid.Column ="0" Grid.Row ="0" Content="Commit" Click="btnCommit_Click"/> <Button x:Name="btnRollback" Height ="30" Width="100" Grid.Column ="1" Grid.Row ="0" Content="Rollback" Click="btnRollback_Click"/> <Button x:Name="btnExit" Height ="30" Width="100" Grid.Column ="2" Grid.Row ="0" Content="Exit" Click="btnExit_Click"/> </Grid> </Grid> </Window>
Это код, стоящий за ним:
using log4net; using Microsoft.Win32; using SharedModels.Models.Pages; using SharedUIForms.Models.ViewModels; using System; using System.Configuration; using System.Globalization; using System.IO; using System.Windows; using System.Windows.Data; using System.Windows.Media; using System.Windows.Media.Imaging; using VTInfrastructure.Other; namespace SharedUIForms { public class ByteArrayToImageSourceConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { byte[] imageData = (byte[])value; BitmapImage biImg = new BitmapImage(); MemoryStream ms = new MemoryStream(imageData); biImg.BeginInit(); biImg.StreamSource = ms; biImg.EndInit(); ImageSource imgSrc = biImg as ImageSource; return imgSrc; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { Stream stream = (Stream)value; Byte[] buffer = null; if (stream != null && stream.Length > 0) { using (BinaryReader br = new BinaryReader(stream)) { buffer = br.ReadBytes((Int32)stream.Length); } } return buffer; } } /// <summary> /// Interaction logic for Person.xaml /// </summary> public partial class Person : Window { public Person(string accessToken, ILog logger) { InitializeComponent(); this.options = new QueryOptions(); AppSettingsReader ar = new AppSettingsReader(); this.ldh = new LocalDataHandler(logger, ar); DataContext = new PersonViewModel(accessToken, this.ldh, this.options, logger); } private void btnCommit_Click(object sender, RoutedEventArgs e) { } private void btnRollback_Click(object sender, RoutedEventArgs e) { } private void btnImage_Click(object sender, RoutedEventArgs e) { BitmapImage bitmapImage; byte[] imageAsByteArray; var of = new OpenFileDialog(); of.Filter = "Image files (*.bmp;*.png;*.jpg;*.jpeg)|*.bmp;*.png;*.jpg;*.jpeg|All files (*.*)|*.*"; var res = of.ShowDialog(); if (res.HasValue) { using (FileStream stream = new FileStream(of.FileName, FileMode.Open, FileAccess.Read)) { using (var reader = new BinaryReader(stream)) { imageAsByteArray = reader.ReadBytes((int)stream.Length); } using (MemoryStream byteStream = new MemoryStream(imageAsByteArray)) { BitmapImage image = new BitmapImage(); image.BeginInit(); image.StreamSource = byteStream; // image.CacheOption = BitmapCacheOption.OnLoad; image.EndInit(); // image.Freeze(); e.Source = image; } } } } private void btnExit_Click(object sender, RoutedEventArgs e) { // Close this window. this.Close(); } #region PRIVATE VARIABLES private LocalDataHandler ldh; QueryOptions options; #endregion } }
И ViewModel:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using VTInfrastructure.Other; using log4net; using SharedModels.Models; using SharedModels.Models.Pages; using System.Threading.Tasks; using System.Windows.Data; using Newtonsoft.Json; namespace SharedUIForms.Models.ViewModels { public class PersonViewModel { private LocalDataHandler ldh; private ILog logger; private string accessToken; private QueryOptions options; public ICollectionView Persons { get; private set; } private IList<CPersonMasterBase> personDataset; public PersonViewModel(string AccessToken, LocalDataHandler Ldh, QueryOptions Options, ILog Logger) { this.ldh = Ldh; this.logger = Logger; this.accessToken = AccessToken; this.options = Options; GetPersonDataSet(); this.Persons = CollectionViewSource.GetDefaultView(this.personDataset); } private async Task GetPersonDataSet() { this.personDataset = new List<CPersonMasterBase>(); var task = this.ldh.GetAllPersons(accessToken, this.options); task.Wait(); // Blocks current thread until GetAllPersons task completes // For pedagogical use only: in general, don't do this! this.personDataset = task.Result; // this.personDataset = await this.ldh.GetAllPersons(accessToken, this.options); } } }
Richard MacCutchan
Как насчет некоторых подсказок относительно того, где находится проблема?
Ger Hayden
Помимо того, что у меня есть в первой строке, когда я помещаю ее в отладку, точка останова в конвертере (класс ByteArrayToImageSourceConverter) не попадает, поэтому я подозреваю, что проблема заключается в этом - я не могу приблизиться к тому, где может лежать проблема. Код работает чисто и просто игнорирует вызов преобразования.
Ger Hayden
Я только что обнаружил ошибку привязки: System.Окна.Данные ошибка: 40 : BindingExpression путь ошибка: 'собственность p_photo' не найден на 'объект' "CPersonMasterBase' (хэш-код=65257631)'. BindingExpression:путь=p_photo; CPersonMasterBase элемента данных='' (хэш-код=65257631); целевой элемент-это 'изображение' (PersonImage имя=''); целевое свойство 'источник' ImageSource ("тип")
И это оказался случай пикника (проблема в кресле, а не в компьютере) - правильное имя свойства-p_Photo, а не p_photo.