2014-01-22 5 views
0

Я пытаюсь извлечь значок в другой поток с помощью IMultiValueConverter, и даже если это работает в другом проекте, здесь он не работает. IsAsync = True запускает конвертер без значения FullPath, а IsAsync = False блокирует пользовательский интерфейс, особенно при извлечении значков из .lnk-файлов.IMultiValueConverter конвертирует путь к значку в другой теме

<Image> 
    <Image.Source> 
    <MultiBinding Converter="{StaticResource Fullpath2Icon}" > 
    <MultiBinding.Bindings> 
     <Binding RelativeSource="{RelativeSource Self}" /> 
     <Binding Path="FullPath" IsAsync="True" /> 
    </MultiBinding.Bindings> 
    </MultiBinding> 
</Image.Source> 
</Image> 


public class Fullpath2IconConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
    System.Windows.Controls.Image image = values[0] as System.Windows.Controls.Image; 
    if (values[1] == null) return null; 
    string mypath = values[1] as string; 

    ThreadPool.QueueUserWorkItem((WaitCallback)delegate 
    { 
     image.Dispatcher.Invoke(DispatcherPriority.Normal, 
      (ThreadStart)delegate { 
       image.Source = System.Drawing.Icon.ExtractAssociatedIcon(mypath).IconToImageSource(); 

Можете ли вы объяснить мне причину этого или предложить какой-либо способ улучшить это?

EDIT: Я создал класс, расширяющий изображение и теперь он выглядит следующим образом:

<local:cIconImage Path="{Binding FullPath}"></local:cIconImage> 

public class cIconImage : System.Windows.Controls.Image 
    { 
     public cIconImage() 
     { 
      //this.Loaded += new RoutedEventHandler(cIconImage_Loaded); 
      Dispatcher.BeginInvoke(DispatcherPriority.Input, new ThreadStart(() => 
      { 
       Source = GetImage(); 
      })); 
     } 

Это намного лучше, так как теперь список населяет, и каждый значок появляется, как она добывается, но в течение некоторого длительного .lnk извлечения пользовательского интерфейса все еще блокируется.

ответ

0

Настройка свойства источника изображения внутри Метод конвертации не имеет никакого смысла. Не говоря уже о вызове Dispatcher.Invoke немедленно в отдельном потоке.

Использование простой привязки на источник собственности, как это:

<Image Source="{Binding FullPath, Converter={StaticResource Fullpath2Icon}}"> 

и одного преобразователя значения, который просто возвращает результат преобразования:

public class Fullpath2IconConverter : IValueConverter 
{ 
    public object Convert(
     object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var mypath = value as string; 
     return System.Drawing.Icon.ExtractAssociatedIcon(mypath).IconToImageSource(); 
    } 

    ... 
} 

Update: Для того, для асинхронной загрузки нескольких изображений значков, вы должны привязать к ObservableCollection<ImageSource> в вашей модели просмотра (без конвертера) и заполнить эту коллекцию из фонового потока. Обратите внимание, что изображения создаются в фоновом потоке и поэтому должны быть заморожены.

public class ViewModel 
{ 
    public ViewModel() 
    { 
     Icons = new ObservableCollection<ImageSource>(); 
    } 

    public ObservableCollection<ImageSource> Icons { get; set; } 

    public void LoadIconsAsync() 
    { 
     ThreadPool.QueueUserWorkItem(o => 
     { 
      foreach (var path in paths) 
      { 
       var image = System.Drawing.Icon.ExtractAssociatedIcon(mypath).IconToImageSource(); 
       image.Freeze(); 

       Application.Current.Dispatcher.Invoke(
        new Action(() => Icons.Add(image))); 
      } 
     }); 
    } 
} 
+0

Я попробовал, что раньше, и добавил «IsAsync = True», но при просмотре сетевых папок, на каждом .lnk или .exe UI файл перестает отвечать на запросы, иногда занимает до 20-х годов на значок. Есть ли лучший способ использовать другой поток там? – Daniel

+0

См. Мое обновление. – Clemens

+0

Невозможно запустить фоновый поток в конвертере? Я сохраняю хранение изображений расширения в словаре (или загрузке, если он уже сохранен) для каждого файла в его IValueConverter, если он не является exe или lnk-файлом. Я не уверен, что это можно сделать элегантной моделью, но должно быть возможно сделать преобразование в фоновом потоке каким-то образом. – Daniel