Reputation: 11990
I have an app written using c# and WPF on the top of Prism 6 framework.
I am trying to create a button using XAMl, when clicked, I want to be pass a fixed decimal value to my view-model.
<Button Content="5"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Command="{Binding ProcessAmount}"
CommandParameter="5.00000"
FontSize="24"
Height="75"
Width="85" />
In my view-model I have the following
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
}
}
But when I compile the app, I get an error in the XAML view Specified cast is not valid.
How can I send a fixed decimal value from the view?
Upvotes: 3
Views: 11028
Reputation: 7325
The problem you have is, that you assign string
"5" to the CommandParameter
. There are several solutions. One of them to set Decimal
in 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>
or handle ComandParameter
as a 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
}
}
Upvotes: 0
Reputation: 2305
In Xaml world, every number is treated as Double
. You would need to cast/ convert manually, otherwise unexpected may occurs. This means, in your view model, retrieve the number as double?
instead of decimal?
, then cast/ convert it to decimal
as appropriately. For ex:
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
}
}
The good thing about this is that it is easier to perform calculation on double
type number than decimal
type number. But, I guess this is not what you wanted.
The solution to your question is specify the type explicitly to be Decimal
in the xaml. You need to import the System mscorlib
and then assign that System
's Decimal
to the 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>
This eliminates the necessary to convert number type on the VM side.
Upvotes: 7
Reputation: 4403
Instead of literally assigning 5.00000
to CommandParameter
, try defining the value in XAML, as a resource (as per this topic). Your XAML code could look something like this
<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>
Upvotes: 2