Boolescher CommandParameter in XAML

76

Ich habe diesen Code (der genau richtig funktioniert):

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

Wobei "s" natürlich der System-Namespace ist.

Dieser Befehl wird jedoch einige Male aufgerufen und bläst den ansonsten recht einfachen XAML-Code wirklich auf. Ist dies wirklich die kürzeste Notation des booleschen Befehlsparameters in XAML (abgesehen von der Aufteilung des Befehls in mehrere Befehle)?

Matěj Zábský
quelle

Antworten:

108

Dies mag ein bisschen hacken, aber Sie können von der KeyBindingKlasse ableiten :

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

Verwendung:

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

Und noch eine nicht so seltsame Lösung:

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>

Verwendung:

<KeyBinding ... CommandParameter="{StaticResource True}"/>
HB
quelle
Dies gilt nicht nur für Tastenkombinationen, sondern auch für Schaltflächen und dergleichen.
Matěj Zábský
Was ist dann mit meiner zweiten Methode, die ich gerade hinzugefügt habe?
HB
1
Interessante Idee, die mir nicht eingefallen ist. Ich werde es versuchen.
Matěj Zábský
@HB Warum gibt meins immer false zurück? Ich kann das nicht zum Laufen bringen.
Igor
2
@HB Schöne Antwort, vielleicht könnten Sie dies hinzufügen: xmlns:s="clr-namespace:System;assembly=mscorlib"zu Ihrer Antwort :)
BendEg
63

Am einfachsten ist es, Folgendes in den Ressourcen zu definieren

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

und benutze es wie:

<Button CommandParameter="{StaticResource FalseValue}"/>
Gordon
quelle
4
und Sie müssen hinzufügen: xmlns:System="clr-namespace:System;assembly=mscorlib"zur Benutzersteuerung
Alex
26

Oder vielleicht das:

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

Wo s ist der Namespace:

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

Ich habe gerade eine noch allgemeinere Lösung mit dieser Markup-Erweiterung gefunden:

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;
    }
}

Verwendung ("wpf:" ist der Namespace, in dem sich die Erweiterung befindet):

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

Sie erhalten sogar die Optionen Trueund Falsenach dem Tippen Bool=und Tippen Sicherheit!

Onur
quelle
@ marbel82 Soweit ich weiß, können Sie die "Erweiterung" genauso wie "Attribut" für Attribute weglassen. Probieren Sie es aus! Aber das Hinzufügen einer Erweiterung wird natürlich nicht schaden.
Onur
Onur du hast recht! Das wusste ich nicht. Sie sollten diese Informationen in die Antwort schreiben. Zuvor habe ich Ihren Code getestet, aber ich hatte woanders einen Fehler.
Marbel82
1
Das ist so schlau, dass es krank ist. Vielen Dank für Ihre Lösung.
John Sully
1
Erstellen Sie einfach eine Markup-Erweiterung pro Typ (z. B. BooleanExtension) und Sie können z. B. CommandParameter={x:Boolean True}ähnlich wie docs.microsoft.com/en-us/dotnet/framework/xaml-services/…
Wouter
6

Vielleicht so etwas wie

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

wo StaticBooleanist

public static class StaticBoolean
{
    public static bool True
    {
        get { return true; }
    }
}
Bala R.
quelle
Ja. Der Wert wird als Zeichenfolge an den Befehl übergeben (was auch nicht das ist, was ich will).
Matěj Zábský
Hmm, wie würde ich den Konverter in diesem Zusammenhang verwenden?
Matěj Zábský
Sorry fand etwas einfacher.
Bala R
1
Das war eine interessante Entwicklung, muss ich sagen, habe alle Schritte gesehen: P Jetzt liegt es an einer Bool-Ressource (die Sie auch in Xaml machen können, wie in meiner Antwort)
HB
Ihre Lösung gefällt mir sehr gut. Ich schlage eine kleine Verbesserung vor. Anstatt geteinfach eine Konstante zu initialisieren public static bool True = true;und eine weitere Konstante hinzuzufügen public static bool False = false;.
Marbel82
1

Hier ist ein weiterer Ansatz, bei dem Sie Ihre eigenen Markup-Erweiterungen definieren, die Trueoder False(oder einen anderen gewünschten Wert) zurückgeben. Dann verwenden Sie sie einfach direkt in XAML wie jede andere Markup-Erweiterung:

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;
}

Sie verwenden sie dann folgendermaßen (vorausgesetzt, Ihr importierter Namespace ist 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}}">

Ich definiere tatsächlich viele benutzerdefinierte MarkupExtensionKlassen für viele allgemeine Dinge, die ich nicht unbedingt in meinen Ressourcen speichern möchte.

Mark A. Donohoe
quelle