【问题标题】:Wpf binding image file to BitmapImage UriSource in MVVM wayWpf以MVVM方式将图像文件绑定到BitmapImage UriSource
【发布时间】:2021-11-06 08:17:44
【问题描述】:

我正在拼命地尝试绑定图像(位于应用程序安装目录的子目录中)。 我正在使用 MVVM 和 .Net 3.5,很难找到图像路径并在属性中返回字符串、Uri 或位图并在 xaml 中使用它。

我尝试将所有这三种格式都绑定到 Images.Resources 中的 UriSource,但它们都不起作用。 我还尝试将 UriSource 与带有 Converter 的 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 + @"..\images\Icon_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>

【问题讨论】:

  • 目前还不清楚您的实际问题是什么。您说“很容易找到图像路径并返回一个字符串,[或]一个 Uri”。这正是您应该做的,公开一个字符串或 Uri 类型的视图模型属性,并将 Image 的 Source 属性绑定到该视图模型属性。内置类型转换会自动创建一个 ImageSource。
  • 在绑定 BitmapImage 的 UriSource 属性时,源属性必须是 Uri,但您通常根本不会这样做。
  • 不起作用,我收到错误消息“必须设置属性 'UriSource' 或属性 'StreamSource'。”
  • 如果你做得对,它确实有效。我们无法确定您是否这样做。
  • 我用更多代码做了一些修改

标签: wpf mvvm binding uri bitmapimage


【解决方案1】:

既不需要 BitmapImage 资源也不需要绑定转换器。

由于从string 到的内置类型转换,这开箱即用 ImageSource:

<Setter Property="Source" Value="{Binding OpenedFolderPath}"/>

在 TreeView 的 ItemTemplate 中,此 Binding 将不起作用,因为它没有预期的 DataContext。你会写

<Setter Property="Source" 
    Value="{Binding DataContext.OpenedFolderPath,
                    RelativeSource={RelativeSource AncestorType=TreeView}}"/>

除此之外,BitmapImage 的UriSource 属性的转换器必须返回一个 Uri,而不是另一个 BitmapImage:

public object Convert(
    object value, Type targetType, object parameter, CultureInfo culture)
{
    return new Uri(value.ToString());
}

【讨论】:

  • 很抱歉,我已经厌倦了您的解决方案,并再次尝试确定。在这种情况下,这些都不起作用。实际上唯一可行的解​​决方案是将图像作为资源嵌入并像这样编写xaml:
  • 图像文件真的在相对于应用程序启动文件夹的子文件夹中吗?或者您是在询问程序集资源,即嵌入在程序集(可执行文件)文件中的文件?您是否尝试过使用相对文件路径而不是从 AppDomain.CurrentDomain.BaseDirectory 创建的绝对路径?
  • 如果文件应该是程序集资源,则其构建操作必须设置为资源,并且您可以从资源文件包 URI(如 pack://application:,,,/Images/Icon_Open.png)加载它。然后,您可以在 XAML 中简单地编写 &lt;Image Source="Images/Icon_Open.png"/&gt;。但是,你为什么要问数据绑定呢?
  • 我已经使用了 4 天了,所以请确保我尝试了您的所有建议。最初的问题是绑定位于应用程序启动文件夹的子文件夹中的图像。我没有收到任何错误,但没有显示图像。我尝试了另一种方法并将图像放入程序集资源中,然后确实 有效,但这并没有回答问题。我想知道为什么绑定不起作用,这就是我发布问题的原因。该图像实际上位于子文件夹中,因为我在 xaml 代码中的其他地方使用它并且它可以工作,它只是在这个 Treeview 上下文中不起作用
  • 好吧,问题当然是TreeViewItem的DataContext与父视图的DataContext不同。 {Binding OpenFolderPath, ...} 因此无法在那里工作,但是当您调试应用程序时,您应该在 Visual Studio 的输出窗口中看到数据绑定错误消息。然而,尚不清楚为什么您有这些数据绑定。假设文件名是固定的,你可以写&lt;Image Source="./Images/Icon_Open.png"/&gt;
猜你喜欢
  • 2015-06-26
  • 2023-03-15
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 2010-09-06
  • 2011-03-10
相关资源
最近更新 更多