【问题标题】:Image gets saved, but won't load [duplicate]图像已保存,但不会加载[重复]
【发布时间】:2016-08-07 09:55:46
【问题描述】:

我可以选择在我的应用程序中添加新客户。客户及其 ID、名称和徽标存储在数据库中。 Logo 只是图像文件的字符串(如 logo.png)

添加徽标似乎很好。当我选择一个图像时,它会显示在 CustomerAddView 中。

添加客户后,CustomerAddView 窗口关闭。客户是在数据库中创建的,数据库中的徽标值很好。
主窗口中的客户列表被刷新 (CustomerListView)。其他客户的徽标工作正常。但是新的客户徽标(使用 AddView 窗口添加)会抛出此警告:

System.Windows.Data Warning: 6 : 'DynamicValueConverter' converter failed to convert value '../../Media/Images/Logos/testlogo.png' (type 'String'); fallback value will be used, if available. BindingExpression:Path=Logo; DataItem='Customer_5A59789E69DE0B010CE32D4E23A696EDB09551158A85050E8CA80E51475D369B' (HashCode=45868004); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource') IOException:'System.IO.IOException: Kan bron media/images/logos/testlogo.png niet vinden.
   bij MS.Internal.AppModel.ResourcePart.GetStreamCore(FileMode mode, FileAccess access)
   bij System.IO.Packaging.PackagePart.GetStream(FileMode mode, FileAccess access)
   bij System.IO.Packaging.PackWebResponse.CachedResponse.GetResponseStream()
   bij System.IO.Packaging.PackWebResponse.GetResponseStream()
   bij System.IO.Packaging.PackWebResponse.get_ContentType()
   bij System.Windows.Media.Imaging.BitmapDecoder.SetupDecoderFromUriOrStream(Uri uri, Stream stream, BitmapCacheOption cacheOption, Guid& clsId, Boolean& isOriginalWritable, Stream& uriStream, UnmanagedMemoryStream& unmanagedMemoryStream, SafeFileHandle& safeFilehandle)
   bij System.Windows.Media.Imaging.BitmapDecoder.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy, Boolean insertInDecoderCache)
   bij System.Windows.Media.Imaging.BitmapFrame.CreateFromUriOrStream(Uri baseUri, Uri uri, Stream stream, BitmapCreateOptions createOptions, BitmapCacheOption cacheOption, RequestCachePolicy uriCachePolicy)
   bij System.Windows.Media.ImageSourceConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   bij MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)
   bij MS.Internal.Data.TargetDefaultValueConverter.Convert(Object o, Type type, Object parameter, CultureInfo culture)
   bij MS.Internal.Data.DynamicValueConverter.Convert(Object value, Type targetType, Object parameter, CultureInfo culture)
   bij System.Windows.Data.BindingExpression.ConvertHelper(IValueConverter converter, Object value, Type targetType, Object parameter, CultureInfo culture)'
System.Windows.Data Error: 11 : Fallback value 'Default' (type 'String') cannot be converted for use in 'Source' (type 'ImageSource'). BindingExpression:Path=Logo; DataItem='Customer_5A59789E69DE0B010CE32D4E23A696EDB09551158A85050E8CA80E51475D369B' (HashCode=45868004); target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource') NullReferenceException:'System.NullReferenceException: De objectverwijzing is niet op een exemplaar van een object ingesteld.
   bij System.Windows.Media.ImageSourceConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   bij System.Windows.Data.BindingExpressionBase.ConvertValue(Object value, DependencyProperty dp, Exception& e)'

我想知道为什么我的徽标图像出现在文件资源管理器中的指定文件夹中,但没有按应有的方式显示在客户列表中。
而且我想知道为什么图像在通过 Visual Studio 的解决方案资源管理器添加时可以工作,但当我通过 CustomerAddView(Model) 添加它们(到同一文件夹)时却不工作。

以下是用于添加新客户的文件: 客户添加视图:

<Grid Margin="5">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="100" />
        </Grid.ColumnDefinitions>

        <TextBlock Name="TBCustomerTitle" FontWeight="Bold">Customer name:</TextBlock>
        <TextBlock Grid.Column="1" FontWeight="Bold" Margin="5,0">*</TextBlock>
        <TextBox Name="TBCustomerData" Grid.Column="2" Grid.ColumnSpan="2"
                 Text="{Binding NewCustomer.Name, UpdateSourceTrigger=PropertyChanged}"></TextBox>

        <TextBlock Grid.Row="1" FontWeight="Bold">Customer logo:</TextBlock>
        <Image Grid.Row="1" Grid.Column="2" MaxHeight="100" MaxWidth="100"
               Source="{Binding NewCustomerLogo, UpdateSourceTrigger=PropertyChanged}" />
        <Button Grid.Row="1" Grid.Column="3" Content="Choose logo" 
                Command="{Binding SelectLogoCommand}"/>

        <TextBlock Margin="0,10" Grid.Row="2" Grid.ColumnSpan="4">Fields marked with * are required fields.</TextBlock>

        <Button Grid.Row="3" Grid.ColumnSpan="4" Margin="0,50,0,0"
                Command="{Binding AddConfirmCommand}">Add this customer</Button>
    </Grid>

客户添加视图模型:

class CustomerAddViewModel : INotifyPropertyChanged
    {
        private RelayCommand addConfirmCommand;
        private RelayCommand selectLogoCommand;
        Image customerLogo;
        string logoDirectory = "../../Media/Images/Logos/";
        DBCustomer dbCustomer = new DBCustomer();

        #region Add Customer
        public ICommand AddConfirmCommand
        {
            get { return addConfirmCommand ?? (addConfirmCommand = new RelayCommand(() => AddConfirmCustomer())); }
        }

        private void AddConfirmCustomer()
        {
            if(newCustomer.Logo != null)
            {                
                customerLogo.Save(logoDirectory + newCustomer.Logo);                
            }
            else
            {
                newCustomer.Logo = "Default.png";
            }
            if (!dbCustomer.Create(newCustomer))
            {
                return;
            }
            App.Messenger.NotifyColleagues("AddCustomerDone");
        }
        #endregion

        #region Add logo
        public ICommand SelectLogoCommand
        {
            get { return selectLogoCommand ?? (selectLogoCommand = new RelayCommand(() => SelectLogo())); }
        }

        private void SelectLogo()
        {
            OpenFileDialog chooseFile = new OpenFileDialog();
            chooseFile.Title = "Select a logo";
            chooseFile.Filter = "All supported graphics|*.jpg;*.jpeg;*.png|" +
              "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|" +
              "Portable Network Graphic (*.png)|*.png";
            if(chooseFile.ShowDialog() == DialogResult.OK)
            {
                Stream reader = File.OpenRead(chooseFile.FileName);
                customerLogo = System.Drawing.Image.FromStream((Stream)reader);

                MemoryStream finalStream = new MemoryStream();
                customerLogo.Save(finalStream, ImageFormat.Png);

                // translate to image source
                PngBitmapDecoder decoder = new PngBitmapDecoder(finalStream, BitmapCreateOptions.PreservePixelFormat,
                                                    BitmapCacheOption.Default);
                NewCustomerLogo = decoder.Frames[0];
                newCustomer.Logo = newCustomer.Name + ".png";
            }            
        }

        private ImageSource newCustomerLogo;
        public ImageSource NewCustomerLogo
        {
            get
            {
                return newCustomerLogo;
            }
            set
            {
                newCustomerLogo = value;
                OnPropertyChanged(new PropertyChangedEventArgs("NewCustomerLogo"));
            }
        }
        #endregion

        private Customer newCustomer = new Customer();
        public Customer NewCustomer
        {
            get { return newCustomer; }
            set { newCustomer = value; OnPropertyChanged(new PropertyChangedEventArgs("NewCustomer")); }
        }

        #region PropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }
        #endregion
    }

客户列表视图

                <ListBox.ItemTemplate>
                <!-- This DataTemplate is used for every Customer object in the ListBox.-->
                <DataTemplate>
                    <Border BorderThickness="2" BorderBrush="Black"
                    Padding="10" Margin="10"
                    Name="CustomerBorder">

                        <Grid Name="ItemGrid">
                            <Grid.RowDefinitions>
                                <RowDefinition/>
                                <RowDefinition/>
                                <RowDefinition/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="100" />
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>

                            <!-- Logo picture -->
                            <Image Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" HorizontalAlignment="Center"
                                   Source="{helpers:ConcatString FrontString=../../Media/Images/Logos/, BindTo={Binding Path=Logo, FallbackValue=Default}}"                         
                                   Height="{Binding ActualHeight, ElementName=ItemGrid}"/>

                            <!-- Customer name Row-->
                            <TextBlock Grid.Row="0" Grid.Column="1" Margin="10,0,8,0" FontWeight="Bold"
                               Name="CustomerTitle">
                               Customer:
                            </TextBlock>
                            <TextBlock Grid.Row="0" Grid.Column="2" 
                               Name="CustomerDataType" 
                               Text="{Binding Path=Name}">
                            </TextBlock>

                            <!-- Environment name Row-->
                            <TextBlock Grid.Row="1" Grid.Column="1" Margin="10,0,8,0" FontWeight="Bold" />
                            <TextBlock Grid.Row="2" Grid.Column="1" Margin="10,0,8,0" FontWeight="Bold" />
                        </Grid>
                    </Border>                    
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

编辑:
此屏幕截图可能会阐明我的困惑。 我通过 CustomerAddView(Model) 添加了 testlogo.png,另外 3 个是在 VS 解决方案资源管理器中添加的。 如您所见:

  • 徽标都在同一个目录中。
  • 只有通过 VS 解决方案资源管理器添加的徽标才会显示在 VS 解决方案资源管理器中。新的没有。
  • 新徽标未显示在 CustomerListView 中。其他人都这样做。

编辑 2:
将图像保存到数据库而不是将文件名保存为数据库中的字符串是否更好?

【问题讨论】:

  • 绑定路径当然应该是NewCustomer.Logo 而不是NewCustomerLogo。除此之外,您不需要在任何单向绑定上设置UpdateSourceTrigger=PropertyChanged。它是多余的,没有任何作用。
  • CustomerAddView 窗口中的绑定工作正常,正如我已经说过的。是 CustomerListView(我刚刚在原始帖子中添加的)在通过 CustomerAddView 添加时没有显示,但是当我将它们直接添加到 Visual Studio 时它们确实有效。
  • 你已经在输出中看到了这个:System.IO.IOException: Kan bron media/images/logos/testlogo.png niet vinden?这显然不是../../media/images/logos/testlogo.png
  • 似乎,从您粘贴的异常来看,他找不到位于media/images/logos/testlogo.png 的图像,这可能是您的问题。
  • 我在原始帖子中添加了屏幕截图。在我决定为用户创建一个功能以通过应用程序添加一个之前,该徽标保存在其他人所在的同一目录中。然而,旧标志有效,而新标志则无效。虽然它们在同一个目录中。它指向正确的目录,根据 Windows 文件资源管理器,它就在那里。 Windows 说是,VS 说不,我的应用程序说不。这就是我感到困惑的地方。

标签: c# wpf image xaml mvvm


【解决方案1】:

MSDN 说:

访问存储在应用程序包中的文件,但从代码 如果没有推断的 root 权限,请指定 ms-appx: 方案。

var uri = new System.Uri("ms-appx:///images/logo.png");

【讨论】:

  • 我尝试在应该获得徽标的 XAML 中使用它,正如我的 OP 中发布的那样。我将图像的 Source 属性更改为 Source="{helpers:ConcatString FrontString=ms-appx:///Media/Images/Logos/, BindTo={Binding Path=Logo, FallbackValue=Default}}" 仍然会引发异常,与 OP 中的大部分相同,但也是一个新异常,它说:NotSupportedException:'System.NotSupportedException: The URI prefix is not recognized 当我刚刚输入 Source="ms-appx: ///Media/Images/Logos/Vodafone.png”(我通过 VS 添加的图像,并且正在工作 b4)它什么都没有显示,没有 img 也没有异常。
  • 那篇 MSDN 文章是关于 Window Store/UWP 应用程序的,而问题是关于 WPF 的。 ms-appx:// URI 在 WPF 中不起作用。
猜你喜欢
  • 1970-01-01
  • 2018-08-30
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
  • 2013-06-15
  • 2018-03-26
  • 2013-05-30
相关资源
最近更新 更多