2008-08-21 36 views
57

Tôi đang cố gắng để ràng buộc một danh sách các đối tượng tùy chỉnh cho một ảnh WPF như thế này:ảnh UriSource and Data Binding

<Image> 
    <Image.Source> 
     <BitmapImage UriSource="{Binding Path=ImagePath}" /> 
    </Image.Source> 
</Image> 

Nhưng nó không hoạt động. Đây là lỗi tôi nhận được:

"Thuộc tính 'UriSource' hoặc thuộc tính 'StreamSource' phải được đặt".

Tôi đang thiếu gì?

Trả lời

74

WPF có trình chuyển đổi tích hợp cho một số loại nhất định. Nếu bạn ràng buộc thuộc tính của Hình ảnh Source thành giá trị string hoặc Uri, dưới mui xe, WPF sẽ sử dụng một số ImageSourceConverter để chuyển đổi giá trị thành số ImageSource.

Vì vậy

<Image Source="{Binding ImageSource}"/> 

sẽ làm việc nếu tài sản ImageSource là một chuỗi đại diện của một URI hợp lệ để một hình ảnh.

Bạn có thể dĩ nhiên lăn chuyển đổi Binding của riêng bạn:

public class ImageConverter : IValueConverter 
{ 
    public object Convert(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return new BitmapImage(new Uri(value.ToString())); 
    } 

    public object ConvertBack(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

và sử dụng nó như thế này:

<Image Source="{Binding ImageSource, Converter={StaticResource ImageConverter}}"/> 
+4

(Trên thực tế bộ chuyển đổi kiểu không tạo ra một 'BitmapImage', nhưng một lớp con của' ImageSource': 'BitmapFrameDecode', là nội bộ.) –

+0

@ H.B. Làm thế nào bạn sẽ chuyển đổi trở lại nếu bạn muốn tiếp tục thay đổi hình ảnh? – Igor

+0

Thay thế cho trình biến đổi: Tạo thuộc tính của bạn mà bạn liên kết với (ở đây: 'ImageSource') của loại' Uri' hoặc 'BitmapImage' và đúc ở đó. Nếu bạn cần xử lý các giá trị 'null' có thể (bỏ qua thất bại, vv), hãy thêm' TargetNullValue = {x: Null} 'vào ràng buộc của bạn. – Gerrit

9

Bạn cần phải triển khai giao diện IValueConverter chuyển đổi uri thành hình ảnh. thực hiện Chuyển đổi lại IValueConverter sẽ giống như thế này:

BitmapImage image = new BitmapImage(); 
image.BeginInit(); 
image.UriSource = new Uri(value as string); 
image.EndInit(); 

return image; 

Sau đó, bạn sẽ cần phải sử dụng bộ chuyển đổi trong ràng buộc của bạn:

<Image> 
    <Image.Source> 
     <BitmapImage UriSource="{Binding Path=ImagePath, Converter=...}" /> 
    </Image.Source> 
</Image> 
19

Bạn cũng có thể chỉ đơn giản là thiết lập các thuộc tính Source thay vì sử dụng con các yếu tố. Để làm điều này, lớp của bạn cần trả về hình ảnh dưới dạng Hình ảnh bitmap. Dưới đây là một ví dụ về một trong những cách tôi đã thực hiện nó

<Image Width="90" Height="90" 
     Source="{Binding Path=ImageSource}" 
     Margin="0,0,0,5" /> 

Và thuộc tính lớp được chỉ đơn giản này

public object ImageSource { 
    get { 
     BitmapImage image = new BitmapImage(); 

     try { 
      image.BeginInit(); 
      image.CacheOption = BitmapCacheOption.OnLoad; 
      image.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 
      image.UriSource = new Uri(FullPath, UriKind.Absolute); 
      image.EndInit(); 
     } 
     catch{ 
      return DependencyProperty.UnsetValue; 
     } 

     return image; 
    } 
} 

Tôi cho rằng nó có thể là một công việc ít hơn bộ chuyển đổi giá trị, nhưng nó là một tùy chọn khác.

+1

Một thực hiện tương tự như sau là hoàn hảo cho khi tài nguyên bitmap của bạn đã được nạp vào đối tượng của bạn và bạn muốn truyền các bit tới ràng buộc. CẢM ƠN! –

23

This article bởi Atul Gupta có mẫu mã bao gồm một số kịch bản:

  1. Liên kết hình ảnh tài nguyên thông thường với Thuộc tính nguồn trong XAML
  2. Hình ảnh tài nguyên ràng buộc, nhưng từ mã phía sau
  3. Hình ảnh tài nguyên ràng buộc trong mã phía sau bằng cách sử dụng Ứng dụng.GetResourceStream
  4. hình ảnh tải từ đường dẫn tập tin qua dòng bộ nhớ (giống được áp dụng khi tải dữ liệu blog hình ảnh từ cơ sở dữ liệu)
  5. tải hình ảnh từ đường dẫn tập tin, nhưng bằng cách sử dụng liên kết với một đường dẫn tập tin tài sản
  6. dữ liệu hình ảnh Binding đến một điều khiển người dùng mà trong nội bộ có quyền kiểm soát hình ảnh thông qua tài sản phụ thuộc
  7. Tương tự như điểm 5, nhưng cũng đảm bảo rằng các tập tin không có được của khóa trên đĩa cứng
6

vấn đề với câu trả lời đó đã được lựa chọn ở đây là khi điều hướng qua lại, trình chuyển đổi sẽ nhận được được kích hoạt mỗi khi trang được hiển thị.

Điều này khiến cho các tệp xử lý mới được tạo liên tục và sẽ chặn mọi nỗ lực xóa tệp vì nó vẫn đang được sử dụng. Điều này có thể được xác minh bằng cách sử dụng Process Explorer.

Nếu các tập tin hình ảnh có thể bị xóa tại một số điểm, bộ chuyển đổi như thế này có thể được sử dụng: using XAML to bind to a System.Drawing.Image into a System.Windows.Image control

Những bất lợi với phương pháp dòng bộ nhớ này là hình ảnh (s) được nạp và giải mã mỗi lần và không có bộ nhớ đệm nào có thể diễn ra: "Để ngăn hình ảnh bị giải mã nhiều lần, hãy gán thuộc tính Image.Source từ Uri thay vì sử dụng luồng bộ nhớ" Nguồn: "Mẹo hiệu suất cho ứng dụng Windows Store sử dụng XAML"

Để giải quyết vấn đề hiệu suất, mẫu kho lưu trữ có thể được sử dụng để cung cấp một lớp lưu trữ. Bộ nhớ đệm có thể diễn ra trong bộ nhớ, có thể gây ra vấn đề về bộ nhớ hoặc dưới dạng tệp hình thu nhỏ nằm trong thư mục tạm thời có thể bị xóa khi ứng dụng thoát.

4

bạn có thể sử dụng

lớp ImageSourceConverter

để có được những gì bạn muốn

img1.Source = (ImageSource)new ImageSourceConverter().ConvertFromString("/Assets/check.png");