簡體   English   中英

WPF-如何在與字符串列表綁定的TextBlock中正確顯示文本

[英]WPF - How to correctly show text in a TextBlock binded with a string list

對於將來的專業項目,我需要評估WPF功能。

在這種情況下,我創建了一個小型測試項目,其中包含1個字符串樹和1個圖像網格。 我希望我的圖像網格顯示給定目錄中包含的所有jpeg圖像,並且對於每個圖像,在圖像下方顯示提取的文件名,而不包含其路徑和擴展名。

實際上,我的演示根據我的目標可以正常工作,除了以下幾點:我添加了每個格式化的文件名,以顯示在List集合內,並嘗試將其與每個圖像底部顯示的TextBlock綁定。 但是,此格式的名稱不可見,而是看到完整的文件名,就像TextBlock直接從Image對象提取它一樣。

在嘗試了幾次教程之后,我嘗試自己解決此問題,但對我來說沒有任何用處。 我無法弄清楚自己在做什么。 有人可以向我解釋嗎?

這是我的XAML文件內容

<Window x:Class="VirtualTrees.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:VirtualTrees"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
            <Setter Property="Visibility" Value="Collapsed" />
        </Style>
        <DataTemplate x:Key="itImageCell">
            <WrapPanel>
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="100"/>
                        <RowDefinition Height="20"/>
                    </Grid.RowDefinitions>
                    <Image Width="120" Stretch="Uniform" Source="{Binding}"/>
                    <TextBlock Grid.Row="1" Width="120" Text="{Binding}" TextTrimming="CharacterEllipsis"/>
                </Grid>
            </WrapPanel>
        </DataTemplate>
        <local:ListToStringConverter x:Key="ListToStringConverter" />
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="400"/>
            <ColumnDefinition Width="400*"/>
        </Grid.ColumnDefinitions>
        <ListView Margin="10" Name="lvStringTree">
            <ListView.View>
                <GridView>
                    <GridViewColumn Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
                    <GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
                    <GridViewColumn Header="Mail" Width="150" DisplayMemberBinding="{Binding Mail}" />
                </GridView>
            </ListView.View>
        </ListView>
        <Grid x:Name="grImages" Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
            <ListView Grid.Row="1" Name="lvImages" ItemsSource="{Binding Path=m_ImageList}" ItemTemplate="{StaticResource itImageCell}">
                <ListView.Background>
                    <ImageBrush/>
                </ListView.Background>
                <ListView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <UniformGrid Columns="3" />
                    </ItemsPanelTemplate>
                </ListView.ItemsPanel>
            </ListView>
            <TextBlock Name="tbImageName" Text="{Binding Path=m_ImageNames, Converter={StaticResource ResourceKey=ListToStringConverter}}" DataContext="{StaticResource itImageCell}" />
        </Grid>
    </Grid>
</Window>

還有我的C#代碼

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace VirtualTrees
{
    [ValueConversion(typeof(List<string>), typeof(string))]
    public class ListToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (targetType != typeof(string))
                throw new InvalidOperationException("The target must be a string");

            return string.Join(", ", ((List<string>)value).ToArray());
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public class User
        {
            public string Name { get; set; }
            public int    Age  { get; set; }
            public string Mail { get; set; }
        }

        List<ImageSource> m_ImageList    = new List<ImageSource>();
        List<string>      m_ImageNames   = new List<string>();
        string            m_RegexPattern = @"\\([\w ]+).(?:jpg|png)$";

        public MainWindow()
        {
            InitializeComponent();

            PopulateStringTree();
            PopulateImageGrid();
        }

        public void PopulateStringTree()
        {
            List<User> vstItems = new List<User>();

            for (ulong i = 0; i < 100000; ++i)
            {
                vstItems.Add(new User() { Name = "John Doe",  Age = 42, Mail = "john@doe-family.com" });
                vstItems.Add(new User() { Name = "Jane Doe",  Age = 39, Mail = "jane@doe-family.com" });
                vstItems.Add(new User() { Name = "Sammy Doe", Age = 7,  Mail = "sammy.doe@gmail.com" });
            }

            lvStringTree.ItemsSource = vstItems;
        }

        public void PopulateImageGrid()
        {
            // get jpeg image file list from target dir
            string       moviePosterPath = @"W:\Labo\WPF\VirtualTrees\VirtualTrees\Resources\Images";
            List<string> fileNames       = new List<string>(System.IO.Directory.EnumerateFiles(moviePosterPath, "*.jpg"));

            // iterate through files
            foreach (string fileName in fileNames)
            {
                // load image and add it to image list
                m_ImageList.Add(new BitmapImage(new Uri(fileName)));
                Console.WriteLine("filename " + fileName);

                // extract image file name and add it to name list
                Match regexMatch = Regex.Match(fileName.Trim(), m_RegexPattern);
                m_ImageNames.Add(regexMatch.Groups[1].Value);
                Console.WriteLine("Movie Name: " + regexMatch.Groups[1].Value);
            }

            // bind data to image grid
            lvImages.ItemsSource = m_ImageList;
        }
    }
}

您的DataTemplate是錯誤的根源。 您必須檢查TextBlock的綁定。 您正在綁定到作為BitmapSourceDataContext TextBlock隱式調用BitmapSource.ToString()以獲取類型的字符串表示形式。 BitmapSource具有ToString()重寫以返回完整的文件路徑。 要解決此問題,您需要使用IValueConverter

修改后的DataTemplate 現在, TextBlock綁定使用轉換器將BitmapSource轉換為文件名:

<DataTemplate x:Key="itImageCell">
  <WrapPanel>
    <Grid>
      <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="20" />
      </Grid.RowDefinitions>
      <Image Width="120"
             Stretch="Uniform"
             Source="{Binding}" />
      <TextBlock Grid.Row="1"
                 Width="120"
                 Text="{Binding ., Converter={StaticResource BitmapSourceToFilenameConverter}}"
                 TextTrimming="CharacterEllipsis" />
    </Grid>
  </WrapPanel>
</DataTemplate>

用於TextBlock綁定的IValueConverter,用於將BitmapSource轉換為文件名:

[ValueConversion(typeof(BitmapSource), typeof(string))]
public class  BitmapSourceToFilenameConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    if (value is BitmapSource bitmapSource)
      return bitmapSource.UriSource.AbsolutePath;

    return Binding.DoNothing;
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}

我在您的代碼中意識到的一個小錯誤:

您首先要在ListView上設置綁定:

<ListView Name="lvImages" ItemsSource="{Binding Path=m_ImageList}" />

然后覆蓋(刪除)它

// bind data to image grid
lvImages.ItemsSource = m_ImageList;

這不是綁定(注釋不正確)。

您應該將m_ImageListObservableCollection<ImageSource>而不是List 當添加,移動或刪除項目時, ObservableCollection將自動更新ListView 然后從您的MainWindow類中刪除以下行: lvImages.ItemsSource = m_ImageList;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM