#wpf #mvvm #binding #uri #bitmapimage
Вопрос:
Я отчаянно пытаюсь привязать образ (который находится в подкаталоге каталога установки приложения). Я использую MVVM и .Net 3.5, легко найти путь к изображению и вернуть строку, Uri или растровое изображение в свойстве и использовать его в xaml.
Я попробовал все эти три формата привязать к UriSource в изображениях.Ресурсы, но ни один из них не работал. Я также попытался связать UriSource со свойством String с помощью конвертера, но безуспешно!
Изображение не отображается.
Возможно ли этого достичь ? Тогда чего же мне не хватает ?
xaml:
<TreeView ItemsSource="{Binding ObCol_FamilyTree}">
<i:Interaction.Behaviors>
<behaviours:BindableTreeViewSelectedItemBehavior SelectedItem="{Binding TreeViewSelectedItem, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<TreeView.Resources>
<Style x:Key="ExpandingImageStyle" TargetType="{x:Type Image}">
<Setter Property="Source" Value="{DynamicResource Icon_Closed}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=IsExpanded}" Value="True">
<Setter Property="Source" Value="{DynamicResource Icon_Open}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ObCol_Items}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="0,0,3,0" Style="{StaticResource ExpandingImageStyle}">
<Image.Resources>
<BitmapImage x:Key="Icon_Closed" UriSource="{Binding OpenFolderPath, Converter={StaticResource UriConverter}}"/>
<BitmapImage x:Key="Icon_Open" UriSource="{Binding OpenFolderPath, Converter={StaticResource UriConverter}}" />
</Image.Resources>
</Image>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Модель представления :
private string myOpenFolderPath;
public ItemListVM()
{
myOpenFolderPath = AppDomain.CurrentDomain.BaseDirectory @"..imagesIcon_Open.png";
if (!File.Exists(myOpenFolderPath))
myOpenFolderPath = String.Empty;
}
public string OpenFolderPath
{
get { return Path.GetFullPath(myOpenFolderPath); }
}
Конвертер :
public class UriConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return new Uri(value.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
Я попробовал то же самое со свойством Uri с правильным преобразователем, который возвращает Uri, больше не повезло!
ИЗМЕНИТЬ : вот решение:
<TreeView ItemsSource="{Binding ObCol_FamilyTree}">
<i:Interaction.Behaviors>
<behaviours:BindableTreeViewSelectedItemBehavior SelectedItem="{Binding TreeViewSelectedItem, Mode=TwoWay}" />
</i:Interaction.Behaviors>
<TreeView.Resources>
<Style x:Key="ExpandingImageStyle" TargetType="{x:Type Image}">
<Setter Property="Source" Value="{Binding DataContext.ClosedFolderPath, RelativeSource={RelativeSource AncestorType=TreeView}}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=TreeViewItem}, Path=IsExpanded}" Value="True">
<Setter Property="Source" Value="{Binding DataContext.OpenFolderPath, RelativeSource={RelativeSource AncestorType=TreeView}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ObCol_Items}">
<StackPanel Orientation="Horizontal">
<Image Width="16" Height="16" Margin="0,0,3,0" Style="{StaticResource ExpandingImageStyle}"/>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Комментарии:
1. Неясно, в чем ваша реальная проблема. Вы говорите, что » легко найти путь к изображению и вернуть либо строку, [или] Uri «. Это именно то, что вам следует сделать, предоставить свойство модели представления типа string или Uri и привязать исходное свойство изображения к этому свойству модели представления. Встроенное преобразование типов автоматически создаст источник изображений.
2. Когда дело доходит до привязки свойства UriSource растрового изображения, исходным свойством должен быть Uri, но обычно вы этого вообще не делаете.
3. <Растровое изображение x:Ключ=»Icon_Closed» UriSource=»{Привязка UriProperty}»/> <Растровое изображение x:Ключ=»Icon_Closed» UriSource=»{Привязка UriProperty}»/><Растровое изображение x:Ключ=»Icon_Closed» UriSource=»{Привязка StringProperty, Конвертер={StaticResource ImageConverter}} }»/> не работает, я получил ошибку «Свойство ‘UriSource’ или свойство ‘Источник потока»должен быть установлен».
4. Это действительно работает, если вы все делаете правильно. Мы не можем сказать, сделали ли вы это.
5. Я внес некоторые правки с большим количеством кода
Ответ №1:
Ни ресурс растрового изображения, ни конвертер привязок не требуются.
Это работает из коробки, благодаря встроенному преобразованию типа из в string
ImageSource
:
<Setter Property="Source" Value="{Binding OpenedFolderPath}"/>
В таблице элементов древовидного представления эта привязка не будет работать, поскольку в ней нет ожидаемого текста данных. Вы бы написали
<Setter Property="Source"
Value="{Binding DataContext.OpenedFolderPath,
RelativeSource={RelativeSource AncestorType=TreeView}}"/>
Кроме того, конвертер для UriSource
свойства растрового изображения должен был бы возвращать Uri, а не другое растровое изображение:
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
return new Uri(value.ToString());
}
Комментарии:
1. Извините, но я уже устал от вашего решения и попробовал еще раз, чтобы убедиться. Все это не работает в данном контексте. Фактически единственным рабочим решением является встраивание изображений в качестве ресурса и написание xaml следующим образом : <Растровое изображение x:Ключ=»Icon_Open» UriSource=»Изображения/Icon_Open.png» />
2. Действительно ли файл изображения находится во вложенной папке относительно папки запуска вашего приложения? Или вы спрашиваете о повторном источнике сборки, т. е. файле, встроенном в файл сборки (исполняемый файл)? Вы пробовали относительный путь к файлу вместо абсолютного пути, созданного из домена приложения? Текущий домен.BaseDirectory?
3. Если файл должен быть ресурсом сборки, для его действия сборки должно быть установлено значение Resource, и вы должны загрузить его из URI пакета файлов ресурсов, например
pack://application:,,,/Images/Icon_Open.png
. В XAML вы могли бы тогда просто написать<Image Source="Images/Icon_Open.png"/>
. Но тогда почему вы вообще спрашиваете о привязке данных?4. Я занимаюсь этим уже 4 дня, так что будьте уверены, что я испробовал все ваши советы. Первоначальная проблема заключается в привязке изображения, которое находится во вложенной папке папки запуска приложения. Я не получаю никаких ошибок, но изображение не отображается. Я попробовал другой способ и поместил изображение в ресурс сборки, а затем действительно <Источник изображения=»Изображения/Icon_Open.png»/> работает, но это не ответ на вопрос. Интересно, почему привязка не работает, вот почему я опубликовал свой вопрос. Изображение действительно находится во вложенной папке, потому что я использую его в другом месте кода xaml, и оно работает, только в этом контексте Treeview это не работает
5. Хорошо, проблема, конечно, в том, что DataContext элемента TreeViewItem отличается от родительского представления.
{Binding OpenFolderPath, ...}
следовательно, там не будет работать, но вы должны были видеть сообщение об ошибке привязки данных в окне вывода в Visual Studio при отладке приложения. Однако неясно, почему у вас вообще есть эти привязки данных. Предполагая, что имена файлов исправлены, вы могли бы просто написать<Image Source="./Images/Icon_Open.png"/>