I've hit a case in which I have a class that returns type object
that I happen to know is merely a boxed int
value. The control I am using can bind to an int
property or a double
property but it cannot bind to an object that is a boxed int
or double
. I have to work around this limitation. I'd like to do so in a very simple manner.
Edited to add: The exception that occurs when I try to do this is System.NotSupportedException
with the message DoubleConverter cannot convert from System.Int32
So is there a way to make a cast to int
or double
in XAML that is the equivalent of an unboxing operation? I already know how to cast a reference type in XAML so I can access some specific, derived-class property. But I am having trouble with this one because int
is not a type with properties.
Below is the class (a simplified version). It represents a ranged set of integers or doubles or even other types for which "min" and "max" values would be meaningful. So it has to return them all as object. Regardless, all 3 properties will return the same underlying type in the boxed value, be it double
or int
or something else.
public class Parameter
{
virtual object Lower { get; }
virtual object Upper { get; }
virtual object Value { get; set; }
}
I bind to the control like this
<tk:RadNumericUpDown MinWidth="100"
IsInteger="True"
Value="{Binding Value, Mode=TwoWay}"
Minimum="{Binding Lower, Mode=OneWay}"
Maximum="{Binding Upper, Mode=OneWay}"
/>
Now if I know that the Lower
property is an int
, can I bind it with some sort of XAML cast? I've tried a few things
Minimum="{Binding Lower(sys:Int32), Mode=OneWay}"
Minimum="{Binding Lower.(sys:Int32), Mode=OneWay}"
I didn't expect any of these to work and they didn't. But the syntax (if there is one) eludes me. About the only way I can get this to work is to define a separate property in the class that returns the Lower
as an int
value
Is there a way to do an unboxing cast in XAML?
CodePudding user response:
You could run it through an IValueConverter
:
public class NonConverter : IValueConverter
{
public object Convert(object v, Type t, object p, CultureInfo c) => v;
public object ConvertBack(object v, Type t, object p, CultureInfo c) => v;
}
Resource:
<Window.Resources>
<local:NonConverter x:Key="nonConverter"></local:NonConverter>
</Window.Resources>
Binding:
Minimum="{Binding Lower, Mode=OneWay, Converter={StaticResource nonConverter}}"
I'm not sure if there is a simpler way.
Here is a minimal implementation using a ProgressBar
, .NET Framework 4.7.2. I'm not sure what happens with two-way binding.
MainWindow.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:local="clr-namespace:WpfApp1"
Title="MainWindow" Height="200" Width="400">
<Window.Resources>
<local:NonConverter x:Key="nonConverter"></local:NonConverter>
</Window.Resources>
<Grid>
<ProgressBar Height="20" Width="200"
Minimum="{Binding Lower}"
Maximum="{Binding Upper, Converter={StaticResource nonConverter}}"
Value="{Binding Value, Converter={StaticResource nonConverter}}"
/>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public object Lower { get; set; }
public object Upper { get; set; }
public object Value { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
Lower = 1000.0d; // double
Upper = "2000"; // string
Value = 1500.0m; // decimal
}
}
public class NonConverter : IValueConverter
{
public object Convert(object v, Type t, object p, CultureInfo c) => v;
public object ConvertBack(object v, Type t, object p, CultureInfo c) => v;
}
}
Each of the three properties are assigned a different type for illustration purposes.
The NonConverter
isn't converting, casting, or un/boxing anything, it's simply returning the same input v
that it received. The actual conversion is being handled by the framework.
Because Lower
is a (boxed) double
, the converter isn't required here.