bagaimana cara melewatkan integer sebagai ConverterParameter?

95

Saya mencoba mengikat ke properti integer:

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

dan konverter saya adalah:

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

masalahnya adalah ketika konverter saya dipanggil, parameternya adalah string. saya membutuhkannya untuk menjadi integer. tentu saja saya dapat mengurai string, tetapi apakah saya harus?

terima kasih atas bantuan konstantin

akonsu
sumber
2
Adakah yang tahu cara mencapai ini di platform Windows Phone di mana kami memiliki sintaks yang sedikit berbeda untuk binding? {Binding PROPERTY, Converter = {StaticResource MYCONVERTER}, ConverterParameter = INT_VAL} dalam contoh ini INT_VAL akan diteruskan sebagai string
Krzysztof Kaczor

Jawaban:

106

Ini dia!

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

Triknya adalah dengan memasukkan namespace untuk tipe sistem dasar dan kemudian menulis setidaknya pengikatan ConverterParameter dalam bentuk elemen.

jpierson.dll
sumber
2
Ini tidak mengubah fakta bahwa jenis IValueConverter.Convert()'s 'parameter' parameter object. Anda masih harus melakukan cast / parse ...
Dan J
6
@djacobson - Benar, tetapi itulah yang diizinkan oleh atribut ValueConversion untuk Anda tentukan. Tidak yakin apakah ini benar-benar digunakan oleh pada waktu kompilasi atau waktu berjalan sama sekali. Dalam kaitannya dengan pertanyaan poster asli dia menetapkan bahwa "saya membutuhkannya menjadi integer. Tentu saja saya dapat mengurai string, tetapi apakah saya harus?" Jadi jawaban saya meringankan bahwa tidak ada parsing string tetapi hanya unboxing integer yang saya masih jauh lebih aman.
jpierson
51

Untuk kelengkapan, satu lagi solusi yang mungkin (mungkin dengan lebih sedikit mengetik):

<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}}" />

(Tentu saja, Windowdapat diganti dengan UserControl, dan IntZerodapat didefinisikan lebih dekat ke tempat penggunaan sebenarnya.)

Vlad
sumber
44

Tidak yakin mengapa WPForang cenderung enggan menggunakan MarkupExtension. Ini adalah solusi sempurna untuk banyak masalah termasuk masalah yang disebutkan di sini.

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

Jika ekstensi markup ini tersedia di XAMLnamespace 'm', maka contoh poster asli menjadi:

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

Ini berfungsi karena parser ekstensi markup dapat melihat tipe kuat dari argumen konstruktor dan mengubahnya sesuai, sedangkan argumen ConverterParameter Binding (kurang informatif) diketik Objek.

Glenn Slayden
sumber
Terima kasih, itu berguna. Ini akan menjadi ekstensi XAML pertama saya. Tapi saya pikir lebih baik untuk membuat Valuesebuah objectdaripada int, untuk menghindari tinju setiap kali di ProvideValue. (Dan kemudian, buatlah privateuntuk menghindari menugaskan sesuatu yang ilegal secara langsung).
Zeus
1
@Zeus Biasanya ProvideValuehanya dipanggil sekali per contoh ekstensi markup, jadi tinju seharusnya hanya dilakukan sekali. Dengan tidak melakukannya di konstruktor, saya sama sekali menghindari tinju jika ProvideValuetidak pernah dipanggil. Sedangkan untuk membuat Valuepribadi, ini akan menghalangi penggunaan ekstensi markup dalam XAMLsintaks elemen objek: msdn.microsoft.com/en-us/library/…
Glenn Slayden
Paragraf terakhir Anda salah. Ini disebut konversi tipe dan juga berlaku untuk properti. Masalahnya, itu Binding.ConverterParametertidak memiliki tipe tertentu (itu hanya an object) sehingga parser tidak tahu konversi apa yang harus diterapkan, maka setiap literal hanya diperlakukan sebagai string.
HB
(Jadi jika ekstensi Anda memiliki konstruktor default, maka {m:Int32 Value=0}akan bekerja dengan baik.)
HB
5

Jangan gunakan value.Equals. Menggunakan:

  Convert.ToInt32(value) == Convert.ToInt32(parameter)
Aliostad
sumber
8
Mengapa Anda tidak ingin menggunakan value.Equals?
Zack
1

Akan lebih baik untuk mengungkapkan informasi tipe untuk ConverterValue di XAML, tapi saya rasa itu tidak mungkin untuk saat ini. Jadi saya kira Anda harus mengurai Objek Konverter ke tipe yang Anda harapkan dengan beberapa logika khusus. Saya tidak melihat cara lain.

SKG
sumber