MSDN.WhiteKnight - Stack Overflow answers
Ответ на "Проверка правильности Image"
Answer 928654
В ходе подробных тестов выяснилось, что используемая схема привязки неудачна во всех отношениях. Помимо того, что нет легкого способа определить момент завершения загрузки изображения, в случае указания в качестве пути к изображению HTTP URI возникают существенные зависания GUI. Это вызвано тем, что хотя и загрузка BitmapImage по HTTP осуществляется асинхронно, разрешение имени узла все равно осуществляется синхронно. На компьютере, где отключен NetBIOS, скорее всего, это не будет иметь заметного эффекта, однако при включенном NetBIOS любое имя, которое не удалось разрешить в DNS, система будет пытаться разрешить широковещательно и это приведет к заметным зависаниям GUI в ходе ввода пути в TextBox (обновление в данной схеме привязки осуществляется при вводе каждого нового символа).
Вместо этого, я предлагаю создать вспомогательный класс для загрузки изображения в фоновом Task с событием окончания загрузки:
public class ImageLoader { Uri _ImageUri; BitmapImage _bi; public BitmapImage Image { get { return _bi; } } public event EventHandler LoadCompleted; void OnLoadCompleted() { if (LoadCompleted != null) LoadCompleted(this, new EventArgs()); } public ImageLoader(Uri uri) { this._ImageUri = uri; } void LoadImage() { BitmapImage bi; try { byte[] data; if (_ImageUri.IsFile) { data = System.IO.File.ReadAllBytes(_ImageUri.LocalPath); } else { var client = new System.Net.WebClient(); using (client) { data = client.DownloadData(_ImageUri); } } var ms = new System.IO.MemoryStream(data); bi = new BitmapImage(); bi.BeginInit(); bi.CacheOption = BitmapCacheOption.OnLoad; bi.StreamSource = ms; bi.EndInit(); bi.Freeze(); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); bi = null; } this._bi = bi; OnLoadCompleted(); } public void Run() { Task t = new Task(() => LoadImage()); t.Start(); } }
Привязку TextBox и Image лучше сделать не напрямую, а через вспомогательные свойства:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WpfApplication1" Height="350" Width="620.522" > <Grid > <Image Width="50" Height="50" Source="{Binding Path=IconImageSource}" Margin="40,40,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"> </Image> <TextBox x:Name="IconPath" Height="35" Text="{Binding Path=IconPathString, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" Margin="139,40,40,0" VerticalAlignment="Top"/> <StatusBar HorizontalAlignment="Stretch" Height="40" VerticalAlignment="Bottom" > <Label Content="{Binding Path=ImageStatusText}"/> </StatusBar> </Grid> </Window>
В код окна добавить логику загрузки изображения и обновления GUI:
using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Threading; using System.Threading.Tasks; using System.ComponentModel; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; namespace WpfApplication1 { public partial class MainWindow : Window, INotifyPropertyChanged { public MainWindow() { InitializeComponent(); this.DataContext = this; } string _IconPathString = ""; ImageLoader Loader = null; public BitmapImage IconImageSource { get { if (Loader != null) return Loader.Image; else return null; } } string _ImageStatusText=""; public string ImageStatusText { get { return _ImageStatusText; } set { _ImageStatusText = value; OnPropertyChanged("ImageStatusText"); } } public string IconPathString { get { return _IconPathString; } set { try { if (Loader != null) { Loader.LoadCompleted -= ImageLoadCompleted; Loader = null; } if (String.IsNullOrEmpty(value)) { _IconPathString = ""; OnPropertyChanged("IconImageSource"); ImageStatusText = "Введите путь к изображению"; return; } Uri uri = new Uri(value); Loader = new ImageLoader(uri); Loader.LoadCompleted += ImageLoadCompleted; Loader.Run(); _IconPathString = value; ImageStatusText = "Подождите..."; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); _IconPathString = ""; OnPropertyChanged("IconImageSource"); ImageStatusText = "Введен неверный путь к изображению"; } } } void ImageLoadCompleted(object sender, EventArgs e) { this.Dispatcher.Invoke(new Action(() => { if ((sender as ImageLoader).Image != null) { ImageStatusText = "Изображение загружено успешно"; } else { _IconPathString = ""; ImageStatusText = "Введен неверный путь к изображению"; } OnPropertyChanged("IconImageSource"); (sender as ImageLoader).LoadCompleted -= ImageLoadCompleted; })); } public event PropertyChangedEventHandler PropertyChanged; void OnPropertyChanged(string name) { var handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(name)); } } }
Content is retrieved from StackExchange API.
Auto-generated by ruso-archive tools.