Чи є у XAML умовна директива компілятора для режиму налагодження?


76

Мені потрібно щось подібне для стилів у XAML:

<Application.Resources>

#if DEBUG
    <Style TargetType="{x:Type ToolTip}">
        <Setter Property="FontFamily" Value="Arial"/>
        <Setter Property="FlowDirection" Value="LeftToRight"/>
    </Style>
#else
    <Style TargetType="{x:Type ToolTip}">
        <Setter Property="FontFamily" Value="Tahoma"/>
        <Setter Property="FlowDirection" Value="RightToLeft"/>
    </Style>
#endif

</Application.Resources>

2
Що ви намагаєтесь досягти?
tsells

2
Мені потрібно мати різні стилі в режимі налагодження, щоб я міг зробити легше виконання в режимі налагодження.
Ehsan Zargar Ershadi

Відповіді:


125

Нещодавно мені довелося це зробити, і я був здивований тим, наскільки просто це було, коли я не міг легко знайти чітких прикладів. Що я зробив, це додав наступне до AssemblyInfo.cs:

#if DEBUG
[assembly: XmlnsDefinition( "debug-mode", "Namespace" )]
#endif

Потім, використовуйте тег AlternateContent для простори імен розмітки, що відповідає сумісності, щоб вибрати вміст на основі презентації цього простору імен:

<Window x:Class="Namespace.Class"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:d="debug-mode"

        Width="400" Height="400">

        ...

        <mc:AlternateContent>
            <mc:Choice Requires="d">
                <Style TargetType="{x:Type ToolTip}">
                    <Setter Property="FontFamily" Value="Arial"/>
                    <Setter Property="FlowDirection" Value="LeftToRight"/>
                </Style>
            </mc:Choice>
            <mc:Fallback>
                <Style TargetType="{x:Type ToolTip}">
                    <Setter Property="FontFamily" Value="Tahoma"/>
                    <Setter Property="FlowDirection" Value="RightToLeft"/>
                </Style>
            </mc:Fallback>
        </mc:AlternateContent>

        ...
</Window>

Тепер, коли визначено DEBUG, буде також визначено "режим налагодження", і буде присутній простір імен "d". Це змушує тег AlternateContent вибрати перший блок коду. Якщо DEBUG не визначено, буде використаний резервний блок коду.

Цей зразок коду не тестувався, але в основному це те саме, що я використовую у своєму поточному проекті, щоб умовно показати деякі кнопки налагодження.

Я бачив допис у блозі з прикладом коду, який спирався на тег "Ігнорується", але це здавалося набагато менш зрозумілим та простим у використанні як цей метод.


5
Панелі помилок VS це не подобається, хоча все працює
належним чином

1
Моє рішення не вдається скомпілювати, коли я додаю код до AssemblyInfo.cs. Я розумію The type or namespace name 'XmlnsDefinitionAttribute' could not be found (are you missing a using directive or an assembly reference?). Що я можу зробити?
nimbudew

1
XmlnsDefinitionAttributeзнаходиться у System.Windows.Markupпросторі імен. Цей простір імен знаходиться у System.Xaml.dllзбірці, яка, на мою думку, додається автоматично при створенні проекту WPF у Visual Studio.
bj0,

1
Якщо ви використовуєте функцію між AlternateContent, яка додає код до методу IComponentConnector.Connect (обробники подій, як OnClick do), то ідентифікатори з'єднання повністю збиваються, і InitializeComponent або вийде з ладу під час виконання, або зробить несподівані дії (перемішайте обробники подій).
springy76

5
Зверніть увагу, що вам може знадобитися позначити "mc" Неприпустимим проти себе, тобто mc: Ignorable = "d mc"
JulieC

2

Ви можете скористатися засобом вибору шаблону. Клас DataTemplateSelector - це те, що ви кодуєте. За допомогою методу вибору шаблону, який ви перевизначаєте, ви можете розмістити директиви препроцесора.

http://msdn.microsoft.com/en-us/library/system.windows.controls.datatemplateselector.aspx


A DataTemplateSelectorможе бути доречним, якщо питання стосувалось змісту альтернативного перегляду , але мова йде про альтернативні стилі - для альтернативних стилів не існує "селектора". Ну, ви можете створити дві окремі копії вмісту, використовуючи різні стилі ... але це не схоже на те, що ви намагаєтесь сказати тут.
ToolmakerSteve

2

Це неможливо в WPF / Silverlight / WP7.

Цікаво відзначити, що стандартний документ, ISO / IEC 29500 , висвітлює, як з цим слід поводитися в XML-документі, а XAML підтримує один із елементів із цієї специфікації, mc:Ignorableщо дозволяє нам робити такі речі:

<Page xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:c="Comments"
      mc:Ignorable="c">
    <Button Content="Some Text"
            c:Content="Some other text" />
</Page>

коментувати атрибути. Я думаю, було б круто, якби XAML одного дня підтримував решту специфікацій, що дозволяють завантажувати альтернативний вміст.

mc:IgnorableАтрибут використовується Blend , функціональності підтримки у час розробки.


1
Яке відношення специфікації формату файлу MS OFfice Open XML до XAML?
Ніколас Кері

Танки, але ця проблема не відповідає моїй ситуації.
Ehsan Zargar Ershadi

Ніколас, команда аналізатора XAML (SL4, WP7.1, WPF) вирішила використовувати цю специфікацію для вирішення своїх потреб в ігноруванні атрибутів, а не просто для вигадування чогось. Ось чому деякі сторінки XAML за замовчуванням мають визначений простір імен 'mc'.
JasonRS Shaver

1

Я відчуваю, що подані відповіді не найпростіші у використанні. Ось моє рішення з використанням спеціальної властивості залежності, що приєднується:

using namespace Utility{
    public static class DebugVisibility
    {
        public static readonly DependencyProperty IsVisibleProperty = DependencyProperty.RegisterAttached(
    "Debug", typeof(bool?), typeof(DebugVisibility), new PropertyMetadata(default(bool?), IsVisibleChangedCallback));

        private static void IsVisibleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var fe = d as FrameworkElement;
            if (fe == null)
                return;
#if DEBUG
            fe.Visibility = Visibility.Visible;
#else
            fe.Visibility = Visibility.Collapsed;
#endif
        }

        public static void SetIsVisible(DependencyObject element, bool? value)
        {
            element.SetValue(IsVisibleProperty, value);
        }

        public static bool? GetIsVisible(DependencyObject element)
        {
            return (bool?)element.GetValue(IsVisibleProperty);
        }
    }
}

і xaml буде використовуватися так:

<window ... xmlns:Util="clr-namespace:MyNamespace.Utility" >
    <Label Util:DebugVisibility.IsVisible="True">
</window>

Я вважав це булітом на випадок, якщо ви хочете додати туди іншу логіку видимості. Це хороший простий перемикач, який можна прив’язати до будь-якого елемента керування та прикріпити до нього


Хороша ідея, але реалізація може бути набагато простішою. Налагодження / випуск, очевидно, не змінюється в середині циклу, тому вам не потрібні всі матеріали зв’язування / залежності. Все, що вам потрібно, це статична змінна "Налагодження" в Util, тобто True при налагодженні та False, коли ні. (І для зручності, другий статичний "Випуск", який є помилковим при налагодженні.) Тоді зробіть <Label IsVisible={Static Util:Debug}.
ToolmakerSteve

1
ПРИМІТКА. Ця відповідь не те саме, що "умовна компіляція"; IsVisible=Falseозначає, що створені об'єкти подання (хоча немає виклику макета). Це має певну вартість, хоча часто незначну - тому для деяких цілей це нормально. Це не корисно для цього конкретного питання , яке стосується альтернативних стилів - IsVisible тут не корисний.
ToolmakerSteve

До речі, якщо ви базували свій код на прикладі, який ви бачили десь ще, ви повинні надати посилання для зарахування автора, код якого допоміг вам це створити. Схоже, тут є складність, щоб дизайнер VS міг побачити ці зміни, про що вже згадувалося тут ; якщо це є причиною складності, то вам слід це згадати.
ToolmakerSteve
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.