WPF:ListBoxItem TextTrimming
WPF: ListBoxItem TextTrimming
我正在与 WPF
一起工作,并且我在一期中堆叠。现在我有 ListBox
。 ListBox
ItemsPanel
是 StackPanel
。当 StackPanel
Orientation
为 Vertical
时,它可以正常工作!
演示:
XAML代码:
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="xmlData" XPath="/records">
<x:XData>
<records xmlns="">
<entry text="Veeeeeeeeeeeeeeeeeeery looooooooooooooooooooooong text"/>
<entry text="A little bit shorter text" />
<entry text="Normal text"/>
</records>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ListBox
ItemsSource="{Binding Source={StaticResource xmlData}, XPath=entry}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=@text}" TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
但是我需要设置StackPanel Orientation Horizontal
。当我设置 Horizontal TextBlock
时,文本没有被修剪。
有解决此问题的想法吗?
谢谢 Jamaxack!
你应该设置 TextBlock.MaxWidth
属性:
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="xmlData" XPath="/records">
<x:XData>
<records xmlns="">
<entry text="Veeeeeeeeeeeeeeeeeeery looooooooooooooooooooooong text"/>
<entry text="A little bit shorter text" />
<entry text="Normal text"/>
</records>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ListBox
ItemsSource="{Binding Source={StaticResource xmlData}, XPath=entry}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock MaxWidth="200" Text="{Binding XPath=@text}" TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
编辑:
为了实现您的目标,您应该使用 MultiValueConverter
并为每个 TextBlock
元素设置宽度:
XAML:
<Window x:Class="WpfListBoxItemTextTrimming.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfListBoxItemTextTrimming">
<Window.Resources>
<local:ListBoxWidthConverter x:Key="listBoxWidthConverter"/>
</Window.Resources>
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="xmlData" XPath="/records">
<x:XData>
<records xmlns="">
<entry text="Veeeeeeeeeeeeeeeeeeery looooooooooooooooooooooong text"/>
<entry text="A little bit shorter text" />
<entry text="Normal text"/>
</records>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ListBox x:Name="LbMBox"
ItemsSource="{Binding Source={StaticResource xmlData}, XPath=entry}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=@text}" TextTrimming="CharacterEllipsis">
<TextBlock.Width>
<MultiBinding Converter="{StaticResource listBoxWidthConverter}">
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" />
<Binding ElementName="LbMBox" Path="Items.Count" />
</MultiBinding>
</TextBlock.Width>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
ListBoxWidthConverter
转换器:
public class ListBoxWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values != null && values.Length == 2)
{
var actualWidth = System.Convert.ToDouble(values[0]);
var numOfItems = System.Convert.ToInt32(values[1]);
return (actualWidth / numOfItems) - 10;
}
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我创建了自定义 Grid
"AutoColumGrid"。
Demo Project
Xaml代码:
<StackPanel>
<Button Click="Button_Click">Add</Button>
<Button Click="Button_Click_1">Remove</Button>
<ListBox Name="uiList" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<local:AutoColumnGrid/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
后面的代码:
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
uiList.Items.Add("Looooooooooooong text 1");
uiList.Items.Add("Normal text 2");
uiList.Items.Add("Short 3");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
uiList.Items.Add("text 4");
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (uiList.Items.Count > 0)
{
uiList.Items.RemoveAt(0);
}
}
自定义网格:
public class AutoColumnGrid : Grid
{
protected override void OnVisualChildrenChanged(System.Windows.DependencyObject visualAdded, System.Windows.DependencyObject visualRemoved)
{
//Checking VisualAdded if it is not null than adding child to Grid
if (visualAdded != null)
{
// Getting column definition count
int columnDefinitionCount = this.ColumnDefinitions.Count;
// Getting child from last, because adds to last
var child = this.Children[columnDefinitionCount];
// Adding new ColumnDefinition
this.ColumnDefinitions.Add(new ColumnDefinition());
// Setting column to child
Grid.SetColumn(child, columnDefinitionCount);
}//Checking VisualRemoved if it is not null than child from Grid
else if (visualRemoved != null)
{
int columnDefinitionIndex = Grid.GetColumn(visualRemoved as UIElement);
this.ColumnDefinitions.RemoveAt(columnDefinitionIndex);
}
Application.Current.MainWindow.Dispatcher.BeginInvoke(new Action(SetColumnWidth));
}
/// <summary>
/// Setts Width to each column
/// if Grid content bigger than window than sets width in percent else if Grid content less than window sets to auto
/// </summary>
private void SetColumnWidth()
{
for (int index = 0; index < this.ColumnDefinitions.Count; index++)
{
var gridActualWidth = this.ActualWidth;
// Getting Grids width
this.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var gridDesiredSize = Convert.ToInt16(this.DesiredSize.Width);
//calculating nesseseryAreaPercent
var nesseseryAreaPercent = gridDesiredSize / gridActualWidth * 100;
//setting column index to child
var child = this.Children[index];
Grid.SetColumn(child, index);
// if nesseseryAreaPercent less or equal 100%, it means grid content is less than grids width and we setting to auto
if (nesseseryAreaPercent <= 100)
{
this.ColumnDefinitions[index].Width = GridLength.Auto;
}
else
{ // Else setting with persent
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
int columnWidth = Convert.ToInt16(child.DesiredSize.Width);
this.ColumnDefinitions[index].Width = new GridLength(columnWidth, GridUnitType.Star);
}
}
}
}
谢谢 Jamshed!
我正在与 WPF
一起工作,并且我在一期中堆叠。现在我有 ListBox
。 ListBox
ItemsPanel
是 StackPanel
。当 StackPanel
Orientation
为 Vertical
时,它可以正常工作!
演示:
XAML代码:
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="xmlData" XPath="/records">
<x:XData>
<records xmlns="">
<entry text="Veeeeeeeeeeeeeeeeeeery looooooooooooooooooooooong text"/>
<entry text="A little bit shorter text" />
<entry text="Normal text"/>
</records>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ListBox
ItemsSource="{Binding Source={StaticResource xmlData}, XPath=entry}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=@text}" TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
但是我需要设置StackPanel Orientation Horizontal
。当我设置 Horizontal TextBlock
时,文本没有被修剪。
有解决此问题的想法吗?
谢谢 Jamaxack!
你应该设置 TextBlock.MaxWidth
属性:
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="xmlData" XPath="/records">
<x:XData>
<records xmlns="">
<entry text="Veeeeeeeeeeeeeeeeeeery looooooooooooooooooooooong text"/>
<entry text="A little bit shorter text" />
<entry text="Normal text"/>
</records>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ListBox
ItemsSource="{Binding Source={StaticResource xmlData}, XPath=entry}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock MaxWidth="200" Text="{Binding XPath=@text}" TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
编辑:
为了实现您的目标,您应该使用 MultiValueConverter
并为每个 TextBlock
元素设置宽度:
XAML:
<Window x:Class="WpfListBoxItemTextTrimming.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfListBoxItemTextTrimming">
<Window.Resources>
<local:ListBoxWidthConverter x:Key="listBoxWidthConverter"/>
</Window.Resources>
<Grid>
<Grid.Resources>
<XmlDataProvider x:Key="xmlData" XPath="/records">
<x:XData>
<records xmlns="">
<entry text="Veeeeeeeeeeeeeeeeeeery looooooooooooooooooooooong text"/>
<entry text="A little bit shorter text" />
<entry text="Normal text"/>
</records>
</x:XData>
</XmlDataProvider>
</Grid.Resources>
<ListBox x:Name="LbMBox"
ItemsSource="{Binding Source={StaticResource xmlData}, XPath=entry}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding XPath=@text}" TextTrimming="CharacterEllipsis">
<TextBlock.Width>
<MultiBinding Converter="{StaticResource listBoxWidthConverter}">
<Binding Path="ActualWidth" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollContentPresenter}}" />
<Binding ElementName="LbMBox" Path="Items.Count" />
</MultiBinding>
</TextBlock.Width>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
ListBoxWidthConverter
转换器:
public class ListBoxWidthConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values != null && values.Length == 2)
{
var actualWidth = System.Convert.ToDouble(values[0]);
var numOfItems = System.Convert.ToInt32(values[1]);
return (actualWidth / numOfItems) - 10;
}
return Binding.DoNothing;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我创建了自定义 Grid
"AutoColumGrid"。
Demo Project
Xaml代码:
<StackPanel>
<Button Click="Button_Click">Add</Button>
<Button Click="Button_Click_1">Remove</Button>
<ListBox Name="uiList" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<local:AutoColumnGrid/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" TextTrimming="CharacterEllipsis"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
后面的代码:
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
uiList.Items.Add("Looooooooooooong text 1");
uiList.Items.Add("Normal text 2");
uiList.Items.Add("Short 3");
}
private void Button_Click(object sender, RoutedEventArgs e)
{
uiList.Items.Add("text 4");
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
if (uiList.Items.Count > 0)
{
uiList.Items.RemoveAt(0);
}
}
自定义网格:
public class AutoColumnGrid : Grid
{
protected override void OnVisualChildrenChanged(System.Windows.DependencyObject visualAdded, System.Windows.DependencyObject visualRemoved)
{
//Checking VisualAdded if it is not null than adding child to Grid
if (visualAdded != null)
{
// Getting column definition count
int columnDefinitionCount = this.ColumnDefinitions.Count;
// Getting child from last, because adds to last
var child = this.Children[columnDefinitionCount];
// Adding new ColumnDefinition
this.ColumnDefinitions.Add(new ColumnDefinition());
// Setting column to child
Grid.SetColumn(child, columnDefinitionCount);
}//Checking VisualRemoved if it is not null than child from Grid
else if (visualRemoved != null)
{
int columnDefinitionIndex = Grid.GetColumn(visualRemoved as UIElement);
this.ColumnDefinitions.RemoveAt(columnDefinitionIndex);
}
Application.Current.MainWindow.Dispatcher.BeginInvoke(new Action(SetColumnWidth));
}
/// <summary>
/// Setts Width to each column
/// if Grid content bigger than window than sets width in percent else if Grid content less than window sets to auto
/// </summary>
private void SetColumnWidth()
{
for (int index = 0; index < this.ColumnDefinitions.Count; index++)
{
var gridActualWidth = this.ActualWidth;
// Getting Grids width
this.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var gridDesiredSize = Convert.ToInt16(this.DesiredSize.Width);
//calculating nesseseryAreaPercent
var nesseseryAreaPercent = gridDesiredSize / gridActualWidth * 100;
//setting column index to child
var child = this.Children[index];
Grid.SetColumn(child, index);
// if nesseseryAreaPercent less or equal 100%, it means grid content is less than grids width and we setting to auto
if (nesseseryAreaPercent <= 100)
{
this.ColumnDefinitions[index].Width = GridLength.Auto;
}
else
{ // Else setting with persent
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
int columnWidth = Convert.ToInt16(child.DesiredSize.Width);
this.ColumnDefinitions[index].Width = new GridLength(columnWidth, GridUnitType.Star);
}
}
}
}
谢谢 Jamshed!