![](/img/trans.png)
[英]WPF when I change the string to which binded Text of TextBlock, the text doesn't change
[英]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
的綁定。 您正在綁定到作為BitmapSource
的DataContext
。 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_ImageList
為ObservableCollection<ImageSource>
而不是List
。 當添加,移動或刪除項目時, ObservableCollection
將自動更新ListView
。 然后從您的MainWindow
類中刪除以下行: lvImages.ItemsSource = m_ImageList;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.