C# 将单个属性的各个组件绑定到WPF中的两个单独控件

C# 将单个属性的各个组件绑定到WPF中的两个单独控件,c#,wpf,binding,multibinding,two-way,C#,Wpf,Binding,Multibinding,Two Way,我的目标是通过两个不同的文本框更新单个大小的属性。具体来说,每个组件都连接到一个文本框,该文本框在下面的XAML中突出显示。特别是说:{Binding Path=Dimensions.Width,…..} private Size _dimension; public Size Dimensions { get { return _dimension; } set { _dimension = value;

我的目标是通过两个不同的文本框更新单个大小的属性。具体来说,每个组件都连接到一个文本框,该文本框在下面的XAML中突出显示。特别是说:{Binding Path=Dimensions.Width,…..}

private Size _dimension;
    public Size Dimensions
    {
        get { return _dimension; }
        set
        {
            _dimension = value;
            OnPropertyChanged("Dimensions");
        }
    }
我的XAML如下所示:

<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
   <Label Content="Width" />
   <TextBox Width="50" Text="{Binding Path=Dimensions.Width, 
            Converter={StaticResource myStringToDoubleConverter},
            UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
   <Label Content="Height" />
   <TextBox Width="50" Text="{Binding Path=Dimensions.Height,
            Converter={StaticResource myStringToDoubleConverter},
            UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</StackPanel>

这是一个组件绑定解决方案,它可以很好地工作

    private Double m_Width;
    public Double Width
    {
        get { return (Dimensions.Width); }
        set
        {
            m_Width = value;
            Dimensions= new Size(m_Width, m_Height);
        }
    }
    private Double m_Height;
    public Double Height
    {
        get { return (Dimensions.Height); }
        set
        {
            m_Height = value;
            Dimensions= new Size(m_Width, m_Height);
        }
    }
    private Size _dimension;
    public Size Dimensions
    {
        get { return _dimension; }
        set
        {
            _dimension = value;
            OnPropertyChanged("Dimensions");
        }
    }

似乎直接绑定到维度。宽度是WPF支持的东西。

下面是组件绑定解决方案,它非常好地工作

    private Double m_Width;
    public Double Width
    {
        get { return (Dimensions.Width); }
        set
        {
            m_Width = value;
            Dimensions= new Size(m_Width, m_Height);
        }
    }
    private Double m_Height;
    public Double Height
    {
        get { return (Dimensions.Height); }
        set
        {
            m_Height = value;
            Dimensions= new Size(m_Width, m_Height);
        }
    }
    private Size _dimension;
    public Size Dimensions
    {
        get { return _dimension; }
        set
        {
            _dimension = value;
            OnPropertyChanged("Dimensions");
        }
    }

似乎WPF支持直接绑定到Dimensions.Width。

如果您在这里使用的
Size
类型是WPF提供的类型,即
System.Windows.Size
,那么问题是它不是一个类。它是一种值类型(即
struct
)。尽管它确实为其
宽度
高度
提供了设置器,但它可能不应该这样做,因为它们没有达到您可能期望的效果

C#也不允许您修改
维度.宽度
-如果您编写以下内容:

src.Dimensions.Width = 123;
如果
src
是包含您在“组件绑定解决方案”中显示的属性定义的类型的实例,则会出现以下错误:

无法修改“WpfApplication1.Source.Dimensions”的返回值,因为它不是变量

C#在这里拒绝,因为同样的基本问题阻止它在WPF中工作:因为
Size
是一种值类型。任何检索
维度
属性的尝试都将返回该值的全新副本

当然,该C#代码实际上是以下内容的缩写:

Size dimensions = src.Dimensions;
dimensions.Width = 123;
C#实际上会让你写这个,但是如果你尝试一下,你会发现为什么它会阻止你写更短的版本:
src.Dimensions.Width
仍然会返回旧的值。(此代码的作用是获取
src.Dimensions
的副本,将该副本存储在名为
Dimensions
的局部变量中,然后修改该局部变量,保持原始变量不变。)

基本上,无法获取对
Size
实例的引用,该实例是
Dimensions
属性返回的实例-您只能获取该值的副本。更新它的唯一方法是在它的位置写一个全新的
Size
。这就是为什么不能单独修改
宽度
高度

试图用转换器解决这个问题是行不通的,因为问题不在于您试图写入目标的值。问题是,您希望写入一个不可访问的目标,即值类型的特定属性。如果绑定是对象的属性而不是值,则只能写入目标属性

(原则上,微软可以让WPF检测到这一点,让它读取
Dimensions
属性,修改它得到的值的副本,然后将修改后的值写回
Dimensions
。虽然在这种情况下这会很方便,但这也将是数据绑定正常处理方式的重大改变我认为他们最好不要尝试,因为这很容易掩盖其他问题。)

在C#中,当你有一个局部变量或字段包含一个
Size
值时,你可以写入单个属性,当然,这是因为变量或字段表示该值的一个特定实例。字段、局部变量、
ref
out
参数和数组元素都是特殊的,因为它们实际上可能o使用它们在原位保存的值。但在查看属性时无法执行此操作。这与定义
列表
时无法写入
myList[0]的原因相同。宽度=123;
,即使使用数组也可以

在任何情况下,可变值类型都有各种各样的问题,不仅仅是因为这个。它们通常是不受欢迎的,不幸的是WPF提供了一些


如果WPF能够绑定到字段,你就可以做你想做的事情。但是它不是,所以你不能。

如果你在这里使用的
Size
类型是WPF提供的类型,即
System.Windows.Size
,那么问题是它不是一个类,而是一个值类型(即
struct
)。尽管它确实为其
宽度
高度
提供了设置器,但它可能不应该这样做,因为它们没有达到您可能期望的效果

C#也不允许您修改
维度.宽度
-如果您编写以下内容:

src.Dimensions.Width = 123;
如果
src
是包含您在“组件绑定解决方案”中显示的属性定义的类型的实例,则会出现以下错误:

无法修改“WpfApplication1.Source.Dimensions”的返回值,因为它不是变量

C#在这里拒绝,因为同样的基本问题阻止它在WPF中工作:因为
Size
是一种值类型。任何试图检索
Dimensions
属性的尝试都将返回该值的全新副本

当然,该C#代码实际上是以下内容的缩写:

Size dimensions = src.Dimensions;
dimensions.Width = 123;
C#实际上会让你写这个,但是如果你尝试一下,你会发现为什么它会阻止你写更短的版本:
src.Dimensions.Width
仍然会返回旧的值。(此代码的作用是获取
src.Dimensions
的副本,将该副本存储在名为
Dimensions
的局部变量中,然后修改该局部变量,保持原始变量不变。)

基本上,无法获取对
Size
实例的引用,该实例是
Dimensions
属性返回的实例-您只能获取该值的副本。而upd的唯一方法是