2012-11-29 36 views
5

Tôi có một lớp tùy chỉnh (để đơn giản hóa công cụ, tôi đã rút gọn các mã):Calling Phương pháp Awaitable trong tài sản accessor [Windows Store Apps/Metro Apps]

public class AlbumItem 
{ 
    public StorageFile AlbumThumbnail { get; set;} 
} 

Khi tôi liên kết này cho một ListView:

<ListView.ItemTemplate> 
      <DataTemplate> 
       <Grid Height="100" Background="#FFabe372"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="80" /> 
         <ColumnDefinition Width="*" /> 
        </Grid.ColumnDefinitions> 
        <Image Source="{Binding AlbumSource}" Margin="10" Stretch="Uniform"></Image> 
        <TextBlock Margin="20 5" Grid.Column="1" Style="{StaticResource AlbumListViewItemStyle}" Text="{Binding AlbumDisplayText}"></TextBlock> 
       </Grid> 

      </DataTemplate> 
</ListView.ItemTemplate> 

nguồn Các Image 's được thiết lập để AlbumSource, như tôi đã nghĩ để thực hiện AlbumSource như một Get tài sản -only:

public class AlbumItem 
{ 
    public StorageFile AlbumThumbnail { get; set;} 

    public BitmapImage AlbumSource 
    { 
     get 
     { 
      BitmapImage bmp = new BitmapImage(); 
      bmp.SetSource(await AlbumThumbnail.OpenReadAsync()); 
      return bmp; 
     } 
    } 
} 

Như dự kiến, tôi không thể sử dụng từ khóa await trong phương thức truy cập, đồng thời tôi không thể khai báo tài sản là phương thức async.

Ai đó có thể chỉ cho tôi đúng hướng không? Tôi có thể đang thử một số Converter sau. Cảm ơn!

Trả lời

7

Người truy cập thuộc tính IMHO phải luôn trả về gần như ngay lập tức. Các hoạt động chạy dài không nên thực thi bên trong một accessor thuộc tính vì điều này có thể có tác động đáng kể bởi vì giả thiết được thừa nhận rộng rãi rằng một accessor về cơ bản là một hoạt động đọc biến (tức là các thuộc tính có thể được truy cập rất nhiều, trong các vòng lặp, không được lưu trữ).

Tôi muốn làm điều gì đó như thế này:

private async Task SetAlbumSourceAsync() 
{ 
    bmp = new BitmapImage(); 
    var source = await AlbumThumbnail.OpenReadAsync(); 
    bmp.SetSource(source); 
    RaisePropertyChanged("AlbumSource"); 
} 

BitmapImage bmp; 
public BitmapImage AlbumSource 
{ 
    get 
    { 
     if (bmp == null) // might need a better sync mechanism to prevent reentrancy but you get the idea 
      SetAlbumSourceAsync(); 

     return bmp; 
    } 
} 
+0

cảm ơn! tôi đã có ý tưởng, nhưng phương pháp của Flavien đã giải quyết được nhu cầu trước mắt của tôi. Tôi sẽ khám phá cách tiếp cận của bạn và xem liệu tôi có thể làm cho nó hoạt động sau này hay không. –

+2

+1 Đây là câu trả lời đúng hơn. Không có lý do kỹ thuật nào mà các thuộc tính 'async' không thể tồn tại; đó là một quyết định thiết kế bởi vì một "bất động sản không đồng bộ" đi ngược lại khái niệm rất của một tài sản. –

+0

Vâng, tôi đã thực hiện các thuộc tính của mình bằng cách sử dụng phương pháp này, và có, nó không làm hỏng giao diện người dùng của tôi! Cảm ơn nhiều! –

2

Nếu bạn sử dụng await, loại trả về sẽ phải là Task<BitmapImage>. Nếu bạn muốn có thể liên kết với XAML của mình, bạn cần trả lại BitmapImage và do đó không thể sử dụng await. Sử dụng Task.Result thay thế:

public BitmapImage AlbumSource 
{ 
    get 
    { 
     BitmapImage bmp = new BitmapImage(); 
     bmp.SetSource(AlbumThumbnail.OpenReadAsync().GetResults()); 
     return bmp; 
    } 
} 
+0

Phương pháp này giải quyết vấn đề của tôi, mặc dù câu trả lời dkackman đã quyết định cho tôi một không gian khác để khám phá, nhờ cả hai! nhưng tôi đã phải thay đổi 'Task.Result' thành' Task.GetResults() '... và lỗi của tôi đối với lỗi cú pháp trên' SetSource' (nên là 'SetSource()' thay thế). –

Các vấn đề liên quan