Удалить поле с первого элемента только в ComboBox

У меня есть ComboBox с разными разделами и заголовками для каждого, Video, Audio, Image.

Используя XAMLStyle, я добавил 7px поле над заголовками, чтобы разделить разделы.

Как я могу удалить только первое поле заголовка, чтобы оно было на одном уровне с верхней частью ComboBox?

Я попытался установить ComboBox<Grid> на Margin = "0,-7,0,0", но это относилось ко всем элементам.

Удалить поле с первого элемента только в ComboBox


Поле со списком

<ComboBox x:Name = "cboContainer" 
          ItemsSource = "{Binding Format_Container_Items}"
          SelectedValuePath = "Name"
          SelectedValue = "{Binding Format_Container_SelectedItem, Mode=TwoWay}"
          Style = "{DynamicResource ComboBoxCustom}"
          ItemContainerStyle = "{DynamicResource ComboBoxCustomItem}" 
          HorizontalAlignment = "Left"
          VerticalAlignment = "Top" 
          Width = "105" 
          Height = "22"
          Margin = "0,2,0,0">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <TextBlock DataContext = "{Binding}">
                    <TextBlock.Text>
                        <Binding Path = "Name"/>
                    </TextBlock.Text>
                </TextBlock>
            </Grid>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

Стиль предмета

<Style x:Key = "ComboBoxCustomItem" TargetType = "{x:Type ComboBoxItem}">
    <Setter Property = "Template" Value = "{StaticResource ComboBoxCustom.Item.ControlTemplate}"/>
    <Setter Property = "Foreground" Value = "#FF000000" />
    <Setter Property = "Background" Value = "#FFFFFFFF" />
    <Setter Property = "BorderBrush" Value = "#FFFFFFFF" />
    <Style.Triggers>

        <!-- Selected -->
        <Trigger Property = "IsSelected" Value = "true">
            <Setter Property = "Foreground" Value = "{StaticResource ComboBoxCustom.Static.Foreground}" />
            <Setter Property = "Background" Value = "{StaticResource ComboBoxCustom.Static.Background}" />
        </Trigger>

        <!-- Mouse Over -->
        <Trigger Property = "IsMouseOver" Value = "true">
            <Setter Property = "Foreground" Value = "{StaticResource ComboBoxCustom.MouseOver.Foreground}" />
            <Setter Property = "Background" Value = "{StaticResource ComboBoxCustom.MouseOver.Background}" />
        </Trigger>

        <!-- Headers -->
        <DataTrigger Binding = "{Binding IsHeader}" Value = "True">
            <Setter Property = "IsEnabled" Value = "False"/>
            <Setter Property = "FontWeight" Value = "Bold"/>
            <!-- 7px Margin Applied Here -->
            <Setter Property = "Margin" Value = "0,7,0,0"/>
        </DataTrigger>
        <DataTrigger Binding = "{Binding IsHeader}" Value = "False">
            <Setter Property = "Margin" Value = "0,0,0,0"/>
        </DataTrigger>

    </Style.Triggers>
</Style>

Источник предметов

public class FormatContainer
{
    public string Name { get; set; }
    public bool IsHeader { get; set; }
}

public List<FormatContainer> _Format_Container_Items = new List<FormatContainer>()
{
    new FormatContainer() { Name = "Video", IsHeader = true  },
    new FormatContainer() { Name = "webm",  IsHeader = false },
    new FormatContainer() { Name = "mp4",   IsHeader = false },
    new FormatContainer() { Name = "mkv",   IsHeader = false },

    new FormatContainer() { Name = "Audio", IsHeader = true  },
    new FormatContainer() { Name = "mp3",   IsHeader = false },
    new FormatContainer() { Name = "m4a",   IsHeader = false },
    new FormatContainer() { Name = "ogg",   IsHeader = false },

    new FormatContainer() { Name = "Image", IsHeader = true  },
    new FormatContainer() { Name = "jpg",   IsHeader = false },
    new FormatContainer() { Name = "png",   IsHeader = false },
    new FormatContainer() { Name = "webp",  IsHeader = false },
};

public List<FormatContainer> Format_Container_Items
{
    get { return _Format_Container_Items; }
    set
    {
        _Format_Container_Items = value;
        OnPropertyChanged("Format_Container_Items");
    }
}

Вы можете установить margin в конце элемента. Нравится Margin = "0 0 0 7"

Cizzl 18.03.2019 08:22

@Cizzl да, но тогда ему нужно было бы установить только последний элемент каждого раздела, так что проблема все еще здесь.

Rafalon 18.03.2019 08:27

Вы можете попробовать использовать AlternationIndex ComboBox в триггере данных, чтобы настроить стиль вашего первого элемента. Или реализовать еще одно свойство внутри Container. Или используйте конвертер XAML, поскольку ответ ниже следует

Pavel Anikhouski 18.03.2019 08:46
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
367
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Если бы я делал это в коммерческом приложении, я бы, вероятно, предоставил свойство в своем FormatContainer, чтобы указать представлению, какой элемент в списке является первым, но это можно сделать в XAML с использованием преобразователя равенства, который возвращает true, когда любые два элемента одинаковы:

public class EqualityConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return Object.Equals(values[0], values[1]);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Затем, вернувшись в свой XAML, вы просто добавляете дополнительный DataTrigger, используя его в качестве преобразователя и передавая как текущий объект, так и первый в исходном списке:

<DataTrigger Value = "True">
    <DataTrigger.Binding>
        <MultiBinding>
            <MultiBinding.Converter>
                <conv:EqualityConverter />
            </MultiBinding.Converter>
            <Binding Path = "DataContext.Format_Container_Items[0]" RelativeSource = "{RelativeSource Mode=FindAncestor, AncestorType=ComboBox}" />
            <Binding />
        </MultiBinding>
    </DataTrigger.Binding>
    <Setter Property = "Margin" Value = "0,0,0,0"/>
</DataTrigger>

Я действительно рекомендую вам обрабатывать это в вашей модели представления, используя обычный DataTrigger. Техники, подобные той, которую я использовал здесь, демонстрируют мощь механизма привязки WPF, но в конце концов вы все равно добавляете логический код к слою представления, который на самом деле ему не принадлежит, даже если он является универсальным. преобразователь.

Ответ принят как подходящий

Что касается самого вопроса, все, что вам нужно, это ItemsPanelTemplate.

        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Margin = "0 -7 0 0"/>
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>

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

public class FormatContainer
{
    public string Name { get; set; }
    public string Category { get; set; }
}

затем сгруппируйте представление Format_Container_Items с Category и используйте ComboBox.GroupStyle для настройки презентации.

Вы можете определить другое свойство, такое как Исфирстхеадер, и добавить маржу только к нему.

Я бы сказал IsNotFirstHeader и добавил поля ко всем заголовкам, кроме первого.

Rekshino 18.03.2019 12:54

Не уверен, что это сработает при применении в качестве триггера стиля, но попробуйте.

<DataTrigger Binding = "{Binding RelativeSource = {RelativeSource PreviousData}}" Value = "{x:Null}">
    <Setter Property = "Margin" Value = "0,0,0,0"/>
</DataTrigger>

Другие вопросы по теме