Wie übergebe ich eine Ganzzahl als ConverterParameter?

95

Ich versuche, an eine Ganzzahl-Eigenschaft zu binden:

<RadioButton Content="None"
             IsChecked="{Binding MyProperty,
                         Converter={StaticResource IntToBoolConverter},
                         ConverterParameter=0}" />

und mein Konverter ist:

[ValueConversion(typeof(int), typeof(bool))]
public class IntToBoolConverter : IValueConverter
{
    public object Convert(object value, Type t, object parameter, CultureInfo culture)
    {
        return value.Equals(parameter);
    }

    public object ConvertBack(object value, Type t, object parameter, CultureInfo culture)
    {
        return value.Equals(false) ? DependencyProperty.UnsetValue : parameter;
    }
}

Das Problem ist, dass beim Aufruf meines Konverters der Parameter string ist. Ich brauche es, um eine ganze Zahl zu sein. Natürlich kann ich den String analysieren, aber muss ich?

danke für jede hilfe konstantin

akonsu
quelle
2
Weiß jemand, wie man dies auf einer Windows Phone-Plattform erreicht, auf der wir eine etwas andere Syntax für Bindungen haben? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} In diesem Beispiel wird INT_VAL als Zeichenfolge übergeben
Krzysztof Kaczor

Antworten:

106

Hier gehts!

<RadioButton Content="None"
             xmlns:sys="clr-namespace:System;assembly=mscorlib">
    <RadioButton.IsChecked>
        <Binding Path="MyProperty"
                 Converter="{StaticResource IntToBoolConverter}">
            <Binding.ConverterParameter>
                <sys:Int32>0</sys:Int32>
            </Binding.ConverterParameter>
        </Binding>
    </RadioButton.IsChecked>
</RadioButton>

Der Trick besteht darin, den Namespace für die grundlegenden Systemtypen einzuschließen und dann mindestens die ConverterParameter-Bindung in Elementform zu schreiben.

jpierson
quelle
2
Dies ändert nichts daran , dass die Art der IValueConverter.Convert()‚s ‚Parameter‘ Parameter ist object. Sie müssen es noch wirken / analysieren ...
Dan J
6
@djacobson - True, aber genau das können Sie mit dem ValueConversion-Attribut angeben. Ich bin mir nicht ganz sicher, ob dies wirklich zur Kompilierungs- oder Laufzeit verwendet wird. In Bezug auf die Frage mit den Originalplakaten gab er an, dass "ich brauche, dass es eine ganze Zahl ist. Natürlich kann ich die Zeichenfolge analysieren, aber muss ich?" Meine Antwort verringert also, dass es keine Analyse einer Zeichenfolge gibt, sondern nur das Auspacken einer Ganzzahl, was für mich noch viel sicherer ist.
Jpierson
51

Der Vollständigkeit halber noch eine mögliche Lösung (möglicherweise mit weniger Eingabe):

<Window
    xmlns:sys="clr-namespace:System;assembly=mscorlib" ...>
    <Window.Resources>
        <sys:Int32 x:Key="IntZero">0</sys:Int32>
    </Window.Resources>

    <RadioButton Content="None"
                 IsChecked="{Binding MyProperty,
                                     Converter={StaticResource IntToBoolConverter},
                                     ConverterParameter={StaticResource IntZero}}" />

( WindowKann natürlich durch ersetzt UserControlwerden und IntZerokann näher am tatsächlichen Verwendungsort definiert werden.)

Vlad
quelle
44

Ich bin mir nicht sicher, warum WPFLeute dazu neigen, nicht zu benutzen MarkupExtension. Es ist die perfekte Lösung für viele Probleme, einschließlich des hier genannten Problems.

public sealed class Int32Extension : MarkupExtension
{
    public Int32Extension(int value) { this.Value = value; }
    public int Value { get; set; }
    public override Object ProvideValue(IServiceProvider sp) { return Value; }
};

Wenn diese Markup-Erweiterung im XAMLNamespace 'm' verfügbar ist, lautet das Beispiel des Originalplakats:

<RadioButton Content="None"
             IsChecked="{Binding MyProperty,
                         Converter={StaticResource IntToBoolConverter},
                         ConverterParameter={m:Int32 0}}" />

Dies funktioniert, weil der Markup-Erweiterungsparser den starken Typ des Konstruktorarguments erkennen und entsprechend konvertieren kann, während das ConverterParameter-Argument von Binding (weniger informativ) objekttypisiert ist.

Glenn Slayden
quelle
Danke, das war nützlich. Es wird meine erste XAML-Erweiterung sein. Aber ich denke, es ist besser, Valueein zu machen, objectals intzu vermeiden, es jedes Mal zu boxen ProvideValue. (Und dann privatevermeiden Sie es, etwas Illegales direkt zuzuweisen).
Zeus
1
@Zeus Wird normalerweise ProvideValuenur einmal pro Markup-Erweiterungsinstanz aufgerufen, daher sollte das Boxen ohnehin nur einmal erfolgen. Wenn ich es nicht im Konstruktor mache, vermeide ich das Boxen ganz, wenn ProvideValuees nie aufgerufen wird. Da für die Herstellung von Valueprivat, würde dies schließt die Markup - Erweiterung bei der Verwendung XAMLObjektelementsyntax: msdn.microsoft.com/en-us/library/...
Glenn Slayden
Ihr letzter Absatz ist falsch. Es heißt Typkonvertierung und gilt auch für Eigenschaften. Die Sache ist, dass Binding.ConverterParameteres keinen bestimmten Typ gibt (es ist nur ein object), so dass der Parser nicht weiß, welche Konvertierung angewendet werden soll, daher wird jedes Literal nur als Zeichenfolge behandelt.
HB
(Wenn Ihre Erweiterung also einen Standardkonstruktor hätte, {m:Int32 Value=0}würde dies genauso gut funktionieren.)
HB
5

Nicht benutzen value.Equals. Verwenden:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)
Aliostad
quelle
8
Warum willst du nicht benutzen value.Equals?
Zack
1

Es wäre schön, die Typinformationen für den ConverterValue in XAML irgendwie auszudrücken, aber ich denke nicht, dass dies ab sofort möglich ist. Ich denke, Sie müssen das Konverterobjekt durch eine benutzerdefinierte Logik auf Ihren erwarteten Typ analysieren. Ich sehe keinen anderen Weg.

SKG
quelle