CharacterEllipsis не работает внутри ItemsControl WPF

Я пытаюсь установить CharacterEllipsis на текст внутри DataTemplate из ItemsControl,

<Window x:Class="CustomPanel.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomPanel;assembly="
Title="Window1" Height="400" Width="400">
<Window.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="TextTrimming" Value="CharacterEllipsis"></Setter>
    </Style>

    <DataTemplate DataType="{x:Type local:Person}">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Name}"
                       Margin="100,0,0,0"/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

    <ItemsControl ItemsSource="{Binding Persons}" 
                  Grid.Column="0">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

</Grid>

Я также попытался установить ширину ItemsControl, StackPanelи TextBlock сам.

Есть идеи?

РЕДАКТИРОВАТЬ

Чтобы подчеркнуть, что это не проблема Style или StackPanelЯ удалил оба, и это все еще не работает

<Window.Resources>
    <DataTemplate DataType="{x:Type local:Person}">
            <TextBlock Text="{Binding Name}"
                       TextTrimming="CharacterEllipsis"
                       Margin="100,0,0,0"
                       Width="200"/>
    </DataTemplate>
</Window.Resources>

<Grid>
    <ItemsControl ItemsSource="{Binding Persons}"/>
</Grid>

осветление

Это прекрасно работает, когда текст слишком велик, но я хочу, чтобы он работал, когда окно также изменяется в меньшую ширину.

4 ответа

Решение

DataTemplate не будет выбирать стиль из окна, поскольку он не находится в этой области. Переместить стиль внутрь DataTemplate.Resources Или же Application.Resources так что он может быть выбран TextBlock внутри DataTemplate.

Во-вторых, вы обернули TextBlock внутри StackPanel, что дает его бесконечный размер для расширения. Итак, удалите Stackpanel, которая оборачивает TextBlock.

В-третьих, ограничьте ширину ItemsControl или установите MaxWidth по своему усмотрению.

<Window.Resources>
    <DataTemplate DataType="{x:Type local:Person}">
        <DataTemplate.Resources>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
            </Style>
        </DataTemplate.Resources>
        <TextBlock Text="{Binding Name}"/>
    </DataTemplate>
</Window.Resources>
<ItemsControl ItemsSource="{Binding Persons}" Width="30">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

ОБНОВИТЬ:

Если вы хотите, чтобы он работал для изменения размера окна, вместо установки ширины, установите максимальную ширину в TextBlock:

<Window.Resources>
    <DataTemplate DataType="{x:Type local:Person}">
        <TextBlock Text="{Binding Name}" MaxWidth="200"
                    TextTrimming="CharacterEllipsis"/>
    </DataTemplate>
</Window.Resources>
<ItemsControl Margin="100,0,0,0" ItemsSource="{Binding Persons}"/>

добавлять x:Key стиль и установить стиль TextBlock, как это:(Рохит Ватс сказал причину)

<Style x:Key="tb" TargetType="{x:Type TextBlock}">
    <Setter Property="TextTrimming" Value="CharacterEllipsis"></Setter>
</Style>

<DataTemplate DataType="{x:Type local:Person}">
    <StackPanel Orientation="Horizontal">
        <TextBlock Width="90" Style="{DynamicResource tb}" Text="{Binding Name}"
               Margin="100,0,0,0"/>
    </StackPanel>
</DataTemplate>

а затем удалите панель стека или установите ширину текстового блока.

результат:

и мой тестовый код:

            Persons = new List<Person>();
            Person p = new Person();
            p.Name="One\ntwo two\nThree Three Three\nfour four four four";
            Persons.Add(p);

другой результат: (изменить размер окна)

код:

<DataTemplate DataType="{x:Type local:Person}">

                <TextBlock Style="{DynamicResource tb}" Text="{Binding Name}"
                       Margin="100,0,0,0"/>

        </DataTemplate>

Короткий ответ:

Удалите свою стековую панель из вашей таблицы данных:

    <DataTemplate DataType="{x:Type local:Person}">
            <TextBlock Text="{Binding Name}" TextTrimming="CharacterEllipsis"/>
    </DataTemplate>

Панель стека занимала все необходимое пространство, поэтому обрезка не работала.

Длинный ответ:

Пример настройки datacontext:

<Window.DataContext>
   <local:PersonsViewModel/>
</Window.DataContext>

Простой вм:

public class PersonsViewModel : INotifyPropertyChanged
{
    private ObservableCollection<Person> persons = new ObservableCollection<Person> { new Person { Name = "Bjarne balblablalblalbal balbalbalballblalbla" }, new Person { Name = "Arne Belinda blblabllalbalblllablalbla Arne Belinda blblabllalbalblllablalbla Arne Belinda blblabllalbalblllablalbla Arne Belinda blblabllalbalblllablalbla Arne Belinda blblabllalbalblllablalbla" }, new Person { Name = "Turid" } };
    public ObservableCollection<Person> Persons
    {
        get { return persons; }
        set
        {
            if (Equals(value, persons)) return;
            persons = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator] // No R#? Comment this line out
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

Класс Person также должен реализовывать INotifyPropertyChanged, чтобы сигнализировать об изменении свойства.

public class Person : INotifyPropertyChanged
{
    private string name;
    public String Name
    {
        get { return name; }
        set
        {
            if (value == name) return;
            name = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

ура

Stian

Это довольно смелое и неверное утверждение. Даже не копируя ваш код в новый проект, я могу понять, почему у вас такая проблема. Для того, чтобы CharacterEllipsis работать, TextBlock необходимо иметь некоторое ограничение на его Width... иначе как бы WPF узнал, когда следует запустить эффект многоточия персонажа?

Одним из решений было бы установить точный Width на TextBlock:

<TextBlock Text="{Binding Name}" Margin="100,0,0,0" Width="200" />

Конечно, это не будет удобно для многих людей, поэтому альтернативой было бы не использовать StackPanel как ItemsPanelTemplate (или в DataTemplate) потому что они позволят TextBlock расти бесконечно.


ОБНОВЛЕНИЕ >>>

Хорошо, у вас есть три возможных решения, потому что Style выходит за рамки сгенерированного DataTemplate элементы:

а) Переместить Style в DataTemplate.Resources:

<DataTemplate DataType="{x:Type local:Person}">
    <DataTemplate.Resources>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="TextBlock.TextTrimming" Value="CharacterEllipsis" />
        </Style>
    </DataTemplate.Resources>
    <TextBlock Text="{Binding Name}" Margin="100,0,0,0"/>
</DataTemplate>

б) Добавить TextTrimming собственность прямо на TextBlock:

<TextBlock Text="{Binding}" TextTrimming="CharacterEllipsis" Margin="100,0,0,0"/>

в) установить Style на TextBlock в явном виде:

<Style x:Key="YourStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="TextBlock.TextTrimming" Value="CharacterEllipsis" />
</Style>

<TextBlock Style="{StaticResource YourStyle}" Text="{Binding}" Margin="100,0,0,0"/>
Другие вопросы по тегам