У нас есть Image и TextBlock, через который мы может задавать источник изображения:
<Image Width="50" Height="50" Source="{Binding ElementName=IconPath, Path=Text}" />
<TextBox x:Name="IconPath"></TextBox>
Я могу ввести в TextBox любой текст - путь к файлу, ссылку или просто абракадабру.
Как определить, ведет ли введенный текст к изображению, которое может быть показано в Image? Другая формулировка вопроса: Как определить, показывается что-либо в Image или там пусто (например, из-за неверного формата файла)?
В ходе подробных тестов выяснилось, что используемая схема привязки неудачна во всех отношениях. Помимо того, что нет легкого способа определить момент завершения загрузки изображения, в случае указания в качестве пути к изображению 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));
}
}
}
Данную проблему можна решить путем проверки строки, кратко говоря проверить на валидность путь.
Это сделать можно с помощью регулярного выражения, например: взять распарсить строку, и просмотреть или в ней находится .jpp|png|svg, если есть, проходим первый этап, дальше попытаться обратиться к картинке, если никаких проблем при этом не возникло, все хорошо.
Вот пример парсинга строки, а вот работа со строками, ну и регулярные выражения.
Вот готовый вариант который можно использовать. Лично моё мнение, достаточно нормальной проверки строки на валидность, а после на наличие элемента по данному пути.
Составил регулярное выражение
(если что не так, прошу великих гуру отписаться в комментарий),
подходит только для полного пути, т.е. D:\\MyFiles\Pictures\pict211.png
.
Делаем проверку строки, соответствует ли она паттерну, и на наличие файла по заданному пути методом Exist
из статического класса File
Вот примерный код:
if (new Regex(@"[A-Z]:\\\\(\w+\\)+\w+((.png)|(.jpeg))").IsMatch(IconPath.Text)
&& File.Exists(IconPath.Text))
{
//делаем то что нам нужно.
}
А вообще, вам бы проверки на наличие, было бы достаточно. Ведь если мы в качестве аргумента передадим абракадабру, то метод просто вернет false
.
Aqua
Не сильно напрягался с расширением файла, если нужны другие форматы делайте вот так:
[A-Z]:\\\\(\w+\\)+\w+((.png)|(.jpeg)|(.format№3)|(.format№4)|...)
где вместо format№n
пишем нужное нам расширение.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Необходимо в контроллере,имея переменную city, простым вызовом
Объясните, пожалуйста, в файле контроллера OrdersController:
Делаю приложение на PHP используя фреймверк LaravelПроблема в том, что после цикла for не срабатывает return, если закомментировать все тело цикла,...