Логічний CommandParameter у XAML


76

У мене є цей код (який працює в самий раз):

<KeyBinding Key="Enter" Command="{Binding ReturnResultCommand}">
    <KeyBinding.CommandParameter>
        <s:Boolean>
            True
        </s:Boolean>
    </KeyBinding.CommandParameter>
</KeyBinding>

Де "s" - це звичайно простір імен System.

Але ця команда викликається кілька разів, і вона насправді роздуває досить простий код XAML. Це насправді найкоротший запис булевого параметра команди в XAML (крім поділу команди на кілька команд)?

Відповіді:


110

Це може бути трохи хак, але ви можете отримати з KeyBindingкласу:

public class BoolKeyBinding : KeyBinding
{
    public bool Parameter
    {
        get { return (bool)CommandParameter; }
        set { CommandParameter = value; }
    }
}

Використання:

<local:BoolKeyBinding ... Parameter="True"/>

І ще одне не дуже дивне рішення:

xmlns:s="clr-namespace:System;assembly=mscorlib"
<Application.Resources>
    <!-- ... -->
    <s:Boolean x:Key="True">True</s:Boolean>
    <s:Boolean x:Key="False">False</s:Boolean>
</Application.Resources>

Використання:

<KeyBinding ... CommandParameter="{StaticResource True}"/>

Це стосується не лише прив’язок клавіш, але й кнопок та інших.
Matěj Zábský

Тоді як щодо мого другого методу, який я щойно додав?
HB

1
Цікава ідея, яка мені не спала на думку. Я спробую.
Matěj Zábský

@HB Чому мій завжди повертає false? Я не можу змусити це працювати.
Ігор

3
@HB Приємна відповідь, можливо, ви могли б додати це: xmlns:s="clr-namespace:System;assembly=mscorlib"до своєї відповіді :)
BendEg

65

Найпростіше визначити наступне в Ресурсах

<System:Boolean x:Key="FalseValue">False</System:Boolean>
<System:Boolean x:Key="TrueValue">True</System:Boolean>

і використовувати його як:

<Button CommandParameter="{StaticResource FalseValue}"/>

5
і вам потрібно додати: xmlns:System="clr-namespace:System;assembly=mscorlib"до користувацького контролю
Олексій

26

Або, можливо, це:

<Button.CommandParameter>
    <s:Boolean>True</s:Boolean>
</Button.CommandParameter>

Де s - простір імен:

 xmlns:s="clr-namespace:System;assembly=mscorlib"

24

Я тільки що знайшов ще більш загальне рішення з цим розширенням розмітки:

public class SystemTypeExtension : MarkupExtension
{
    private object parameter;

    public int Int{set { parameter = value; }}
    public double Double { set { parameter = value; } }
    public float Float { set { parameter = value; } }
    public bool Bool { set { parameter = value; } }
    // add more as needed here

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return parameter;
    }
}

Використання ("wpf:" - це простір імен, в якому живе розширення):

<KeyBinding Key="F8" Command="{Binding SomeCommand}" CommandParameter="{wpf:SystemType Bool=True}"/>

Ви навіть отримуєте варіанти Trueі Falseпісля набору тексту Bool=та безпеку набору тексту !


@ marbel82, наскільки мені відомо, ви можете пропустити "Розширення" так само, як "Атрибут" для атрибутів. Спробуйте самі! Але додавання розширення, звичайно, не зашкодить.
Онур

Онур ти маєш рацію! Я цього не знав. Ви повинні написати цю інформацію у відповіді. Раніше я тестував ваш код, але десь ще мав помилку.
marbel82

1
Це так гладко, що хворіє. Дякуємо за ваше рішення.
Джон Саллі,

1
Просто створіть розмітку для кожного типу (наприклад BooleanExtension), і ви можете написати, наприклад, CommandParameter={x:Boolean True}подібні до docs.microsoft.com/en-us/dotnet/framework/xaml-services/…
Wouter

6

Можливо щось подібне

<KeyBinding Key="Enter" Command="{Binding ReturnResultCommand}"
    CommandParameter="{x:Static StaticBoolean.True}" />

де StaticBooleanє

public static class StaticBoolean
{
    public static bool True
    {
        get { return true; }
    }
}

Так. Значення передається в команду як рядок (що також не те, що я хочу).
Matěj Zábský

Хм, як мені використовувати перетворювач у цьому контексті?
Matěj Zábský

Вибачте, знайшов щось простіше.
Bala R

1
Це була цікава еволюція, я повинен сказати, побачив усі кроки: P Тепер справа до ресурсу bool (що ви могли б зробити і в Xaml, як у моїй відповіді)
HB

Мені дуже подобається ваше рішення. Я пропоную невелике вдосконалення. Замість того, щоб getпросто ініціалізувати константу public static bool True = true;і додати іншу константу public static bool False = false;.
marbel82

1

Ось ще один підхід, коли ви визначаєте власні розширення розмітки, які повертають Trueабо False(або будь-яке інше значення, яке ви бажаєте). Тоді ви просто використовуєте їх прямо в XAML, як і будь-яке інше розширення розмітки:

public class TrueExtension : MarkupExtension {
    public override object ProvideValue(IServiceProvider serviceProvider) => true;
}

public class FalseExtension : MarkupExtension {
    public override object ProvideValue(IServiceProvider serviceProvider) => false;
}

public class DoubleExtension : MarkupExtension {
    public DoubleExtension(){};
    public DoubleExtension(double value) => Value = value;
    public double Value { get; set; }
    public override object ProvideValue(IServiceProvider serviceProvider) => Value;
}

Потім ви використовуєте їх таким чином (припускаючи, що імпортований простір імен є mx):

<KeyBinding Key="Enter"
    Command="{Binding ReturnResultCommand}"
    CommandParameter="{mx:True}" />

<Button Visibility="{Binding SomeProperty,
    Converter={SomeBoolConverter},
    ConverterParameter={mx:True}}">

<!-- This guarantees the value passed is a double equal to 42.5 -->
<Button Visibility="{Binding SomeProperty,
    Converter={SomeDoubleConverter},
    ConverterParameter={mx:Double 42.5}}">

Я фактично визначаю безліч власних MarkupExtensionкласів для багатьох загальних речей, які я не хочу зберігати в своїх ресурсах.

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