我可以在 XAML 中使用强制转换来取消装箱整数吗?

发布于 2025-01-10 06:33:53 字数 1450 浏览 0 评论 0原文

我遇到过这样的情况:我有一个返回类型 object 的类,我碰巧知道它只是一个装箱的 int 值。我使用的控件可以绑定到 int 属性或 double 属性,但它无法绑定到装箱的对象 intdouble。我必须解决这个限制。我想以一种非常简单的方式做到这一点。

编辑添加:当我尝试执行此操作时发生的异常是System.NotSupportedException,并显示消息DoubleConverter无法从System.Int32转换

所以有没有办法在 XAML 中进行强制转换为 intdouble ,相当于拆箱操作?我已经知道如何在 XAML 中转换引用类型,以便可以访问某些特定的派生类属性。但我在这个问题上遇到了麻烦,因为 int 不是一种具有属性的类型。

下面是该类(简化版本)。它表示一组范围内的整数或双精度数,甚至是“最小”和“最大”值有意义的其他类型。所以它必须将它们全部作为对象返回。无论如何,所有 3 个属性都将在装箱值中返回相同的基础类型,无论是 double 还是 int 或其他类型。

public class Parameter
{
    virtual object Lower      { get; }     
    virtual object Upper      { get; }   
    virtual object Value      { get; set; } 
}

我像这样绑定到控件

<tk:RadNumericUpDown MinWidth="100"
    IsInteger="True"
    Value="{Binding Value, Mode=TwoWay}"
    Minimum="{Binding Lower, Mode=OneWay}"
    Maximum="{Binding Upper, Mode=OneWay}"
    />

现在,如果我知道 Lower 属性是 int,我可以使用某种 XAML 强制转换来绑定它吗?我尝试了一些

Minimum="{Binding Lower(sys:Int32), Mode=OneWay}"
Minimum="{Binding Lower.(sys:Int32), Mode=OneWay}"

我没想到会起作用的事情,但它们没有。但语法(如果有的话)让我困惑。我可以让它工作的唯一方法是在类中定义一个单独的属性,该属性将 Lower 返回为 int

有没有办法进行拆箱强制转换在 XAML 中?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

花辞树 2025-01-17 06:33:53

您可以通过 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;
}

资源:

<Window.Resources>
    <local:NonConverter x:Key="nonConverter"></local:NonConverter>
</Window.Resources>

绑定:

Minimum="{Binding Lower, Mode=OneWay, Converter={StaticResource nonConverter}}"

我不确定是否有更简单的方法。


以下是使用 ProgressBar、.NET Framework 4.7.2 的最小实现。我不确定双向绑定会发生什么。

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

出于说明目的,这三个属性中的每一个都被分配了不同的类型。

NonConverter 不会转换、转换或拆箱任何内容,它只是返回收到的相同输入 v。实际的转换由框架处理。

由于 Lower 是一个(盒装的)double,因此此处不需要转换器。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文