Как применить несколько стилей в WPF

Только заполнить друзей массива.

User.findOne({ _id: "userId"})
.populate('friends')
.exec((err, user) => {
    //do something
});

Результат такой же:

{
    "_id" : "userId",
    "name" : "John",
    "age" : 30,
    "friends" : [
        { "_id" : "userId1", "name" : "Derek", "age" : 34 }
        { "_id" : "userId2", "name" : "Homer", "age" : 44 }
        { "_id" : "userId3", "name" : "Bobby", "age" : 12 }
    ]
}

То же самое: Mongoose - использование Populate в массиве ObjectId

140
задан MojoFilter 19 August 2008 в 12:47
поделиться

6 ответов

я думаю, что простой ответ - то, что Вы не можете сделать (по крайней мере, в этой версии WPF), что Вы пытаетесь сделать.

таким образом, для какого-то конкретного элемента только один Стиль может быть применен.

Однако, поскольку другие имеют вышеизложенный, возможно, можно использовать BasedOn для выручения Вас. Проверьте следующую часть свободного xaml. В нем Вы будете видеть, что у меня есть основной стиль, который устанавливает свойство, которое существует на базовом классе элемента, к которому я хочу применить два стиля. И, во втором стиле, который основан на основном стиле, я установил другое свойство.

Так, идея здесь... состоит в том, если можно так или иначе разделить свойства, которые Вы хотите установить... согласно иерархии наследования элемента, на котором Вы хотите установить несколько стилей..., у Вас могло бы быть обходное решение.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <Style x:Key="baseStyle" TargetType="FrameworkElement">
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style TargetType="Button" BasedOn="{StaticResource baseStyle}">
            <Setter Property="Content" Value="Hello World"/>
        </Style>
    </Page.Resources>
    <Grid>
        <Button Width="200" Height="50"/>
    </Grid>
</Page>


Hope это помогает.

Примечание:

Одна вещь в особенности для замечания. Если Вы изменяетесь TargetType во втором стиле (в первом наборе xaml выше) к ButtonBase, два Стиля не становятся прикладными. Однако проверьте следующий xaml ниже для обхождения того ограничения. В основном это означает, что необходимо дать Стилю ключ и сослаться на него с тем ключом.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Page.Resources>
        <Style x:Key="baseStyle" TargetType="FrameworkElement">
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style x:Key="derivedStyle" TargetType="ButtonBase" BasedOn="{StaticResource baseStyle}">
            <Setter Property="Content" Value="Hello World"/>
        </Style>
    </Page.Resources>
    <Grid>
        <Button Width="200" Height="50" Style="{StaticResource derivedStyle}"/>
    </Grid>
</Page>
144
ответ дан akjoshi 19 August 2008 в 12:47
поделиться
  • 1
    Муравей и Ivy самостоятельно развертываются к Nexus repo в Apache, таким образом, нет определенно никаких проблем с интеграцией Плюща/Nexus. – Brian Fox 6 June 2010 в 02:16

Но можно расшириться от другого.. смотрите на свойство

<Style TargetType="TextBlock">
      <Setter Property="Margin" Value="3" />
</Style>

<Style x:Key="AlwaysVerticalStyle" TargetType="TextBlock" 
       BasedOn="{StaticResource {x:Type TextBlock}}">
     <Setter Property="VerticalAlignment" Value="Top" />
</Style>
BasedOn
31
ответ дан akjoshi 19 August 2008 в 12:47
поделиться

WPF/XAML не обеспечивает эту функциональность исходно, но это действительно обеспечивает расширяемость, чтобы позволить Вам делать то, что Вы хотите.

Мы столкнулись с той же потребностью и закончили тем, что создали наше собственное Расширение Разметки XAML (который мы назвали "MergedStylesExtension"), чтобы позволить нам создавать новый стиль из двух других стилей (который, в случае необходимости, мог, вероятно, использоваться многократно подряд для наследования еще большему количеству стилей).

из-за ошибки WPF/XAML, мы должны использовать синтаксис элемента свойства для использования его, но кроме которого это, кажется, работает хорошо. Например,

<Button
    Content="This is an example of a button using two merged styles">
    <Button.Style>
      <ext:MergedStyles
                BasedOn="{StaticResource FirstStyle}"
                MergeStyle="{StaticResource SecondStyle}"/>
   </Button.Style>
</Button>

я недавно записал об этом здесь: http://swdeveloper.wordpress.com/2009/01/03/wpf-xaml-multiple-style-inheritance-and-markup-extensions/

17
ответ дан 19 August 2008 в 12:47
поделиться
  • 1
    Можно ли объяснить типы функций, которые делают его устойчивым/настраивающимся на уровне птичьего глаза? – cwash 24 June 2009 в 16:39

если Вы не касаетесь никаких определенных свойств, можно получить всю основную и общую собственность к стилю, который является целевым типом, был бы FrameworkElement. тогда, можно создать определенные ароматы для каждой цели, вводит Вас потребность, без потребности копирования всей той общей собственности снова.

1
ответ дан Greg 19 August 2008 в 12:47
поделиться
  • 1
    Как обновление, Sonatype opensourced их LDAP поддерживают для Nexus с этими 1,5 выпусками в начале 2010. – Ophidian 3 May 2010 в 18:40

Можно, вероятно, получить что-то подобное при применении этого к набору объектов при помощи StyleSelector, я использовал это для приближения к подобной проблеме в использовании различных стилей на TreeViewItems в зависимости от связанного типа объекта в дереве. Вам, вероятно, придется изменить класс ниже немного для корректировки к конкретному подходу, но надо надеяться это получит Вас, запустился

public class MyTreeStyleSelector : StyleSelector
{
    public Style DefaultStyle
    {
        get;
        set;
    }

    public Style NewStyle
    {
        get;
        set;
    }

    public override Style SelectStyle(object item, DependencyObject container)
    {
        ItemsControl ctrl = ItemsControl.ItemsControlFromItemContainer(container);

        //apply to only the first element in the container (new node)
        if (item == ctrl.Items[0])
        {
            return NewStyle;
        }
        else
        {
            //otherwise use the default style
            return DefaultStyle;
        }
    }
}

, Вы тогда применяете это как так

 <TreeView>
     <TreeView.ItemContainerStyleSelector
         <myassembly:MyTreeStyleSelector DefaultStyle="{StaticResource DefaultItemStyle}"
                                         NewStyle="{StaticResource NewItemStyle}" />
     </TreeView.ItemContainerStyleSelector>
  </TreeView>
1
ответ дан Dave 19 August 2008 в 12:47
поделиться
  • 1
    О, " случай study" на блоге sonatype, как беспристрастный. Почему don' t Вы просто связываются с продуктом и позволяют людям составить свои собственные умы. – Brad 3 September 2009 в 08:11

Платформа XNA проста в использовании и хорошо работает, поскольку на самом деле просто оболочка для DirectX. Большим преимуществом является то, что вы можете писать весь свой код на управляемом C #. Посмотрите этот пост на форуме xna, чтобы узнать, как вы можете считывать данные с дисплея для экспорта.

под заголовком «Как я могу установить несколько стилей в WPF?»

Этот блог сейчас мертв, поэтому я воспроизводю сообщение здесь


WPF и Silverlight предлагают возможность получить стиль из другого стиля через Свойство «Базедон». Эта функция позволяет разработчикам организовывать свои стили, используя иерархию, аналогичную наследованию классов. Рассмотрим следующие стили:

<Style TargetType="Button" x:Key="BaseButtonStyle">
    <Setter Property="Margin" Value="10" />
</Style>
<Style TargetType="Button" x:Key="RedButtonStyle" BasedOn="{StaticResource BaseButtonStyle}">
    <Setter Property="Foreground" Value="Red" />
</Style>

С этим синтаксисом для Button, использующего RedButtonStyle, свойство Foreground будет установлено на Red, а свойство Margin - на 10.

Эта функция существует в WPF в течение долгого времени, и она новое в Silverlight 3.

Что если вы хотите установить более одного стиля для элемента? Ни WPF, ни Silverlight не предлагают готового решения этой проблемы. К счастью, есть способы реализовать это поведение в WPF, которые я расскажу в этом сообщении блога.

WPF и Silverlight используют расширения разметки для предоставления свойствам значений, для получения которых требуется некоторая логика. Расширения разметки легко узнать по фигурным скобкам, окружающим их в XAML. Например, расширение разметки {Binding} содержит логику для извлечения значения из источника данных и его обновления при возникновении изменений; расширение разметки {StaticResource} содержит логику для получения значения из словаря ресурсов на основе ключа. К счастью для нас, WPF позволяет пользователям писать свои собственные расширения разметки. Эта функция пока отсутствует в Silverlight, поэтому решение в этом блоге применимо только к WPF.

Другие написали отличные решения для объединения двух стилей с использованием расширений разметки. Однако, Мне нужно было решение, которое обеспечивало бы возможность объединения неограниченного количества стилей, что немного сложнее.

Написание расширения разметки несложно. Первый шаг - создать класс, производный от MarkupExtension, и использовать атрибут MarkupExtensionReturnType, чтобы указать, что вы хотите, чтобы значение, возвращаемое вашим расширением разметки, было типа Style.

[MarkupExtensionReturnType(typeof(Style))]
public class MultiStyleExtension : MarkupExtension
{
}

Определение входных данных для расширения разметки

Мы ' Я бы хотел дать пользователям нашего расширения разметки простой способ указать стили для объединения. По сути, есть два способа, которыми пользователь может указать входные данные для расширения разметки. Пользователь может устанавливать свойства или передавать параметры конструктору. Поскольку в этом сценарии пользователю требуется возможность указать неограниченное количество стилей, Мой первый подход заключался в создании конструктора, который принимает любое количество строк с использованием ключевого слова «params»:

public MultiStyleExtension(params string[] inputResourceKeys)
{
}

Моя цель состояла в том, чтобы иметь возможность записывать входные данные следующим образом:

<Button Style="{local:MultiStyle BigButtonStyle, GreenButtonStyle}" … />

Обратите внимание на запятую, разделяющую ключи разных стилей. К сожалению, пользовательские расширения разметки не поддерживают неограниченное количество параметров конструктора, поэтому такой подход приводит к ошибке компиляции. Если бы я знал заранее, сколько стилей я хочу объединить, я мог бы использовать тот же синтаксис XAML с конструктором, принимающим желаемое количество строк:

public MultiStyleExtension(string inputResourceKey1, string inputResourceKey2)
{
}

В качестве обходного пути я решил, что параметр конструктора принимает одну строку, которая задает имена стилей, разделенные пробелами. Синтаксис неплох:

private string[] resourceKeys;

public MultiStyleExtension(string inputResourceKeys)
{
    if (inputResourceKeys == null)
    {
        throw new ArgumentNullException("inputResourceKeys");
    }

    this.resourceKeys = inputResourceKeys.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

    if (this.resourceKeys.Length == 0)
    {
        throw new ArgumentException("No input resource keys specified.");
    }
}

Вычисление вывода расширения разметки

Чтобы вычислить вывод расширения разметки, нам нужно переопределить метод из MarkupExtension под названием «ProvideValue». Значение, возвращаемое этим методом, будет установлено в целевом объекте расширения разметки.

Я начал с создания метода расширения для Style, который знает, как объединить два стиля. Код для этого метода довольно прост:

public static void Merge(this Style style1, Style style2)
{
    if (style1 == null)
    {
        throw new ArgumentNullException("style1");
    }
    if (style2 == null)
    {
        throw new ArgumentNullException("style2");
    }

    if (style1.TargetType.IsAssignableFrom(style2.TargetType))
    {
        style1.TargetType = style2.TargetType;
    }

    if (style2.BasedOn != null)
    {
        Merge(style1, style2.BasedOn);
    }

    foreach (SetterBase currentSetter in style2.Setters)
    {
        style1.Setters.Add(currentSetter);
    }

    foreach (TriggerBase currentTrigger in style2.Triggers)
    {
        style1.Triggers.Add(currentTrigger);
    }

    // This code is only needed when using DynamicResources.
    foreach (object key in style2.Resources.Keys)
    {
        style1.Resources[key] = style2.Resources[key];
    }
}

С помощью приведенной выше логики первый стиль модифицируется для включения всей информации из второго. Если есть конфликты (например, оба стиля имеют сеттер для одного и того же свойства), второй стиль выигрывает. Обратите внимание, что помимо копирования стилей и триггеров, я также принял во внимание значения TargetType и BasedOn, а также любые ресурсы, которые может иметь второй стиль. Для TargetType объединенного стиля я использовал тот тип, который является более производным. Если второй стиль имеет стиль «Базедон», я рекурсивно объединяю его иерархию стилей. Если у него есть ресурсы, Копирую их в первый стиль. Если эти ресурсы упоминаются с помощью {StaticResource}, они статически разрешаются до выполнения этого кода слияния, и поэтому перемещать их не нужно. Я добавил этот код на случай, если мы используем DynamicResources.

Показанный выше метод расширения позволяет использовать следующий синтаксис:

style1.Merge(style2);

Этот синтаксис полезен при условии, что у меня есть экземпляры обоих стилей в ProvideValue. Я не знаю. Все, что я получаю от конструктора, - это список строковых ключей для этих стилей. Если бы в параметрах конструктора была поддержка params, я мог бы использовать следующий синтаксис для получения фактических экземпляров стиля:

<Button Style="{local:MultiStyle {StaticResource BigButtonStyle}, {StaticResource GreenButtonStyle}}" … />
public MultiStyleExtension(params Style[] styles)
{
}

Но это не работает. И даже если бы ограничения параметров не существовало, мы, вероятно, столкнулись бы с другим ограничением расширений разметки, где нам пришлось бы использовать синтаксис элемента свойства вместо синтаксиса атрибута для указания статических ресурсов, что является подробным и громоздким (я лучше объясню эту ошибку в предыдущей записи блога ). И даже если бы обоих этих ограничений не существовало, я бы все равно написал список стилей, используя только их имена - он короче и проще для чтения, чем StaticResource для каждого из них.

Решение состоит в том, чтобы создать StaticResourceExtension, используя код. Имея ключ стиля типа string и поставщика услуг, я могу использовать StaticResourceExtension для получения фактического экземпляра стиля. Вот синтаксис:

Style currentStyle = new StaticResourceExtension(currentResourceKey).ProvideValue(serviceProvider) as Style;

Теперь у нас есть все части, необходимые для написания метода ProvideValue:

public override object ProvideValue(IServiceProvider serviceProvider)
{
    Style resultStyle = new Style();

    foreach (string currentResourceKey in resourceKeys)
    {
        Style currentStyle = new StaticResourceExtension(currentResourceKey).ProvideValue(serviceProvider) as Style;

        if (currentStyle == null)
        {
            throw new InvalidOperationException("Could not find style with resource key " + currentResourceKey + ".");
        }

        resultStyle.Merge(currentStyle);
    }
    return resultStyle;
}

Вот полный пример использования расширения разметки MultiStyle:

<Window.Resources>
    <Style TargetType="Button" x:Key="SmallButtonStyle">
        <Setter Property="Width" Value="120" />
        <Setter Property="Height" Value="25" />
        <Setter Property="FontSize" Value="12" />
    </Style>

    <Style TargetType="Button" x:Key="GreenButtonStyle">
        <Setter Property="Foreground" Value="Green" />
    </Style>

    <Style TargetType="Button" x:Key="BoldButtonStyle">
        <Setter Property="FontWeight" Value="Bold" />
    </Style>
</Window.Resources>

<Button Style="{local:MultiStyle SmallButtonStyle GreenButtonStyle BoldButtonStyle}" Content="Small, green, bold" />

enter image description here

44
ответ дан 23 November 2019 в 22:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: