WPF bağlaması kullanarak iki komut parametresini iletme


155

Aşağıdaki standart sözdizimini kullanarak XAML dosyamdan yürüttüğüm bir komut var:

<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand}"/>

Bu işlemin kullanıcıların beklediği şekilde (tuvalin genişliği ve yüksekliği spesifik olarak) tamamlamak için görünümden İKİ bilgi parçasına ihtiyacım olduğunu fark edene kadar bu iyi çalıştı.

Komutum için bir argüman olarak bir dizi geçirmek mümkün gibi görünüyor, ancak CommandParameter benim iki tuval özellikleri için bağlayıcı belirtmek için bir yol olduğunu görmüyorum:

<Button Content="Zoom" 
        Command="{Binding MyViewModel.ZoomCommand" 
        CommandParameter="{Binding ElementName=MyCanvas, Path=Width}"/>

Hem Genişliği hem de Yüksekliği komutuma nasıl iletirim? Bu XAML komutlarını kullanarak mümkün gibi görünmüyor ve benim yakınlaştırma yöntemine geçmek için bu bilgileri almak için kodumda bir tıklama işleyicisi tel gerekir.


[ stackoverflow.com/questions/58114752/… yukarıdaki çözüm. Aynı sorunu
yaşadım

Yanıtlar:


240

İlk olarak, MVVM yapıyorsanız, bu bilgileri görünümünüzden ayrı ayrı özellikler aracılığıyla VM'niz için kullanılabilir hale getirirsiniz. Bu, herhangi bir parametreyi komutlarınıza iletmenizden kurtarır.

Bununla birlikte, parametreleri oluşturmak için çoklu bağlayabilir ve bir dönüştürücü kullanabilirsiniz:

<Button Content="Zoom" Command="{Binding MyViewModel.ZoomCommand">
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource YourConverter}">
             <Binding Path="Width" ElementName="MyCanvas"/>
             <Binding Path="Height" ElementName="MyCanvas"/>
        </MultiBinding>
    </Button.CommandParameter>
</Button>

Dönüştürücünüzde:

public class YourConverter : IMultiValueConverter
{
    public object Convert(object[] values, ...)
    {
        return values.Clone();
    }

    ...
}

Ardından, komut yürütme mantığınızda:

public void OnExecute(object parameter)
{
    var values = (object[])parameter;
    var width = (double)values[0];
    var height = (double)values[1];
}

1
Teşekkürler Kent - tam da aradığım şey buydu. İlk yaklaşımınızı daha iyi beğeniyorum, böylece VM, parametreleri hiç geçirmek zorunda kalmadan bir bağlanma yoluyla görünümün "durumunu" biliyor, ancak yine de test edebilirim. Bunun benim için işe yarayacağından emin değilim, çünkü tuvali mümkün olduğunca büyük hale getirmek ve bu değeri VM'ye geçirmek için görünüme ihtiyacım var. Bağlarsam, VM'deki genişliği ayarlamam gerekmez mi? Hangi durumda, VM görünüme bağlıdır?
JasonD

@ Jason: her iki şekilde de yapabilirsiniz. Yani, görünüm itme değişikliklerini görünüm modeline geri döndürün veya görünüm modelinin değişiklikleri görünümde itmesini sağlayın. TwoWay bağlaması, her iki seçeneğin de kullanılmasına neden olur.
Kent Boogaart

Benim programımda OnExecute yöntemi parametresi null değerleri olan bir dizi, ancak dönüştürücüde değerler beklendiği gibi
Alex David

2
OnExecute yönteminde parametrenin null olduğunu buldum, ayrıca düğmeyi tıkladıktan sonra YourConverter.Convert () çağrılmadı. Neden?
SubmarineX

3
Bu işe yaramaz, bir düğmeye basıldığında parametreler boştur
adminSoftDK

38

Seçilen çözümün dönüştürücüsünde, değer eklemelisiniz. Aksi takdirde komut sonunda yer alan parametreler null

public class YourConverter : IMultiValueConverter
{
    public object Convert(object[] values, ...)
    {
        return values.Clone();
    }

    ...
}

6
Merhaba, Clone () ile bu ek çalışma yapar :) Açıklayabilir misiniz, ne fark eder. Clone () 'un çalışmasının neden gerekli olduğunu anlamıyorum? Teşekkür ederim.
adminSoftDK

Yanılıyor olabilirim, ama bu (satır 1267) bana neden olabilir gibi: referenceource.microsoft.com/#PresentationFramework/src/…
maxp

14

Dönüştürücü'de Tuple'i kullanın ve OnExecute'de parametre nesnesini tekrar Tuple'a aktarın.

public class YourConverter : IMultiValueConverter 
{      
    public object Convert(object[] values, ...)     
    {   
        Tuple<string, string> tuple = new Tuple<string, string>(
            (string)values[0], (string)values[1]);
        return (object)tuple;
    }      
} 

// ...

public void OnExecute(object parameter) 
{
    var param = (Tuple<string, string>) parameter;
}

5

Değerleriniz statikse aşağıdakileri kullanabilirsiniz x:Array:

<Button Command="{Binding MyCommand}">10
  <Button.CommandParameter>
    <x:Array Type="system:Object">
       <system:String>Y</system:String>
       <system:Double>10</system:Double>
    </x:Array>
  </Button.CommandParameter>
</Button>

" Değerleriniz statikse ": Statik kaynak nedir? Örneğin soru Kanvas Genişliği ve Yüksekliğinden bahsediyor. Bu değerler sabit değildir, ancak statik midir? Bu durumda XAML ne olurdu?
dakika

2
"Statik" yerine "sabit" yazmalıydım. Statik kaynak, yürütme sırasında değişmeyen bir kaynaktır. Eğer kullanırsanız SystemColors, örneğin, kullanmak gerekir DynamicResourceyerine StaticResourcekullanıcı yürütme sırasında Kontrol Paneli aracılığıyla sistem renklerini değiştirebilirsiniz çünkü. Tuval Widthve Heightkaynak değildir ve statik değildir. Kaynağından devralınan örnek özellikleri var FrameworkElement.
Maxence

2

Tuple'i Converter'da kullanma hakkında 'string' yerine 'object' kullanmak daha iyi olur, böylece 'string' nesnesinin sınırlaması olmaksızın tüm nesne türleri için çalışır.

public class YourConverter : IMultiValueConverter 
{      
    public object Convert(object[] values, ...)     
    {   
        Tuple<object, object> tuple = new Tuple<object, object>(values[0], values[1]);
        return tuple;
    }      
} 

O zaman Command'daki yürütme mantığı şöyle olabilir

public void OnExecute(object parameter) 
{
    var param = (Tuple<object, object>) parameter;

    // e.g. for two TextBox object
    var txtZip = (System.Windows.Controls.TextBox)param.Item1;
    var txtCity = (System.Windows.Controls.TextBox)param.Item2;
}

ve parametreleri oluşturmak için dönüştürücü ile çoklu bağlama (iki TextBox nesnesiyle)

<Button Content="Zip/City paste" Command="{Binding PasteClick}" >
    <Button.CommandParameter>
        <MultiBinding Converter="{StaticResource YourConvert}">
            <Binding ElementName="txtZip"/>
            <Binding ElementName="txtCity"/>
        </MultiBinding>
    </Button.CommandParameter>
</Button>

Dönüştürücüyü kaç parametre desteklediğinden daha açık olduğu için bunu beğendim. Sadece iki parametre için iyi! (Ayrıca XAML ve Command'ın tam kapsama alanı için işlevi yürüttüğünü gösterdiniz)
Caleb W.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.