Как передать десятичное значение в качестве CommandParameter для команды, использующей WPF? - PullRequest
0 голосов
/ 09 мая 2018

У меня есть приложение, написанное с использованием c # и WPF поверх платформы Prism 6.

Я пытаюсь создать кнопку с использованием XAMl, при нажатии я хочу передать фиксированное десятичное значение моей модели представления.

<Button Content="5"
        VerticalAlignment="Center"
        HorizontalAlignment="Center"
        Command="{Binding ProcessAmount}"
        CommandParameter="5.00000"
        FontSize="24"
        Height="75"
        Width="85" />

В моей модели просмотра у меня есть следующее

public class ViewModel : BindableBase
{
    public DelegateCommand<decimal?> ProcessAmount { get; set; }

    public ViewModel()
    {
        ProcessAmount = new DelegateCommand<decimal?>(HandleProcessAmount, CanProcessAmount);
    }

    private bool CanProcessAmount(decimal? amount)
    {
        return amount.HasValue && amount.Value != 0;
    }

    private void HandleProcessAmount(decimal? amount)
    {
        // do something with the amount
    }
}

Но когда я компилирую приложение, я получаю сообщение об ошибке в представлении XAML Specified cast is not valid.

Как я могу отправить фиксированное десятичное значение из представления?

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

В мире Xaml каждое число рассматривается как Double. Вам нужно будет выполнить приведение / преобразование вручную, иначе может произойти неожиданное Это означает, что в вашей модели представления получите число как double? вместо decimal?, а затем приведите / преобразуйте его в decimal соответствующим образом. Например:

public class ViewModel : BindableBase
{
    public DelegateCommand<double?> ProcessAmount { get; set; }

    public ViewModel()
    {
        ProcessAmount = new DelegateCommand<double?>(HandleProcessAmount, CanProcessAmount);
    }

    private bool CanProcessAmount(double? amount)
    {
        return amount.HasValue && amount.Value != 0;
    }

    private void HandleProcessAmount(double? amount)
    {
        decimal amountInDecimal = Convert.ToDecimal(amount.Value); // convert it to decimal

        // do something with the amount
    }
}

Хорошо, что в этом случае вычисление для номера типа double проще, чем для номера типа decimal. Но, думаю, это не то, что вы хотели.

Решение вашего вопроса - указать тип, явно равный Decimal в xaml. Вам необходимо импортировать System mscorlib, а затем присвоить System Decimal CommandParameter.

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

<Button Content="5"
        VerticalAlignment="Center"
        HorizontalAlignment="Center"
        Command="{Binding ProcessAmount}"
        FontSize="24"
        Height="75"
        Width="85">
    <Button.CommandParameter>
        <s:Decimal>5.00000</s:Decimal>
    </Button.CommandParameter>
</Button>

Это исключает необходимость преобразования чисел на стороне виртуальной машины.

0 голосов
/ 09 мая 2018

Проблема в том, что вы присваиваете string "5" для CommandParameter. Есть несколько решений. Один из них для установки Decimal в XAML:

<Window x:Class="....." 
xmlns:sys="clr-namespace:System;assembly=mscorlib"  
/>
<Button Content="5"
    VerticalAlignment="Center"
    HorizontalAlignment="Center"
    Command="{Binding ProcessAmount}"
    FontSize="24"
    Height="75"
    Width="85">
    <Button.CommandParameter><sys:Decimal>5.00000</sys:Decimal></Button.CommandParameter>
    <!-- <Button.CommandParameter><x:Null/></Button.CommandParameter> If you want to set value to null-->
</Button>


или ручкой ComandParameter как string:

public class ViewModel : BindableBase
{
    public DelegateCommand<string> ProcessAmount { get; set; }

    public ViewModel()
    {
        ProcessAmount = new DelegateCommand<string>(HandleProcessAmount, CanProcessAmount);
    }

    private bool CanProcessAmount(string amountStr)
    {
        try
        {
            return Convert.ToDecimal(amountStr) != 0;
        }
        catch (Exception)
        {
            return false;
        }
    }

    private void HandleProcessAmount(string amount)
    {
        // do something with the amount
    }
}
0 голосов
/ 09 мая 2018

Вместо буквального присвоения 5.00000 для CommandParameter, попробуйте определить значение в XAML как ресурс (согласно этой теме ). Ваш XAML-код может выглядеть примерно так

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        xmlns:system="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow"
        Height="450"
        Width="800">

    <Window.Resources>
        <system:Double x:Key="MyDouble">5.0000</system:Double>
    </Window.Resources>

    <Grid>
        <Button Content="5"
                VerticalAlignment="Center"
                HorizontalAlignment="Center"
                Command="{Binding ProcessAmount}"
                CommandParameter="{StaticResource MyDouble}"
                FontSize="24"
                Height="75"
                Width="85" />
    </Grid>
</Window>
...