绑定不更新。 (属性 家长变更?!)

Binding does not update. (Property change of Parent?!)

我在更新绑定时遇到问题。 但我认为解释我的问题的最简单方法是我的代码:

XAML

<StackPanel>
        <StackPanel.Resources>
            <Converter:Converter_Position x:Key="Position"/>
        </StackPanel.Resources>
        <TextBox Text="{Binding Path=Position.X, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox Text="{Binding Path=Position, Converter={StaticResource PositionToStartPosition}, UpdateSourceTrigger=PropertyChanged}"/>
 </StackPanel>

如果我更改第一个文本框的文本,第二个文本框不会更新。

我的转换器:

class Converter_Position : IValueConverter
{
    public object Convert(object value, Type t, object parameter, CultureInfo culture)
    {
        RaPoint Position = value as RaPoint;
        return Position.ToString();
    }

    public object ConvertBack(object value, Type t, object parameter, CultureInfo culture)
    {
        throw new Exception();
    }
}

邦德Class:

public class RaPoint : INodifyPropertyChanged
    {
        public RaPoint()
        {
            X = 0;
            Y = 0;
        }

        public RaPoint(double X, double Y)
        {
            this.X = X;
            this.Y = Y;
        }

        private const string XPropertyName = "X";
        private double _X;
        public double X
        {
            get
            {
                return _X;
            }
            set
            {
                _X = value;
                RaisePropertyChanged(XPropertyName);
            }
        }

        private const string YPropertyName = "Y";
        private double _Y;
        public double Y
        {
            get
            {
                return _Y;
            }
            set
            {
                _Y = value;
                RaisePropertyChanged(YPropertyName);
            }
        }

        public override string ToString()
        {
            return String.Format("X:{0} Y:{1}" , X.ToString(), Y.ToString());
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }

数据上下文:

private const string PositionPropertyName = "Position";
private RaPoint _Position = new RaPoint();
public RaPoint Position
{
    get
    {
        return _Position;
    }
    set
    {
        _Position = value;
        RaisePropertyChanged(PositionPropertyName);
    }
}

如果您将 Window 的 DataContext 设置为 RaPoint 实例 (Position 属性),那么您应该尝试以这种方式绑定:

<TextBox Text="{Binding Path=X, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding  Converter={StaticResource PositionToStartPosition}, UpdateSourceTrigger=PropertyChanged}"/>

基本上,数据绑定在不同对象的两个属性之间建立连接。在第一行中,您绑定了在 DataContext 中设置的对象的 属性。 Path 用于指定该对象的 属性 或者可能指向 属性 的 属性 (假设 X 有一个 属性 Z,那么你可以做类似 Path=X.Z).

的事情

关于第二个 TextBox,如果您未指定绑定的 SourcePathRelativeSourceElementName,则绑定将使用控件的 DataContext。 DataContext 通过视觉树从上层元素(例如 Window)传递到下层元素(在您的情况下为 TextBox)。

但是这些建议并不能解决您的问题。当您更改第一个 TextBox 中 X 的值时,Position属性 永远不会更改,因此不会调用 RaisePropertyChanged,第二个 TextBox 也不会调用以 X 的新值更新。如果您想要一个具有 XY 值的文本框,则使用 MultiBinding。在您的 Window/UserControl 中执行此操作:

<TextBox Text="{Binding Path=X, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox>
    <TextBox.Text>
      <MultiBinding Converter="{StaticResource Position}">
          <Binding Path="X" />
          <Binding Path="Y" />
       </MultiBinding>
    </TextBox.Text>
</TextBox>

并以这种方式更改您的转换器:

public class Converter_Position : IMultiValueConverter
{

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        return String.Format("X:{0} Y:{1}", values[0],values[1]); 
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

问题是转换器只在加载时使用一次。 Position DataContext 永远不会改变,所以在位置 属性 的 setter 中有一个 RaisePropertyChnage 是没有意义的。删除那个。

public RaPoint Position
{
    get
    {
        return _Position;
    }
    set
    {
        _Position = value;
        RaisePropertyChanged(PositionPropertyName);
    }
}

public RaPoint Position
{
   get; set;
}

接下来是您希望 TextBoxX 更新时更新,因此理想情况下,您不想简单地绑定到 Position(因为 DataContext 只被改变一次),你想绑定到 Position.X 因为那是 属性 changed 事件所在的地方。通过这样做,转换器将在每次 X 更改时进行评估。不过,您还只需要在转换器中传递的 Position class 。您将需要更新转换器,以便将 Position 传递给它。最简单的方法是使用 MultiValuConverter 传递到参数对象以及 Paramter.X(将用于监视更改)。

<TextBox>
    <TextBox.Text>
            <MultiBinding Converter="{StaticResource PositionToStartPosition}">
                <Binding Path="Position.X" UpdateSourceTrigger="PropertyChanged"/>
                <Binding Path="Position" />
            </MultiBinding>
    </TextBlock.Text>
</TextBox>

最后,更新您的转换器:

class Converter_Position : IMultiValueConverter
{
    public object Convert(object[] values, Type t, object parameter, CultureInfo culture)
    {
        RaPoint Position = values[1] as RaPoint;
        return Position.ToString();
    }

    public object ConvertBack(object[] values, Type t, object parameter, CultureInfo culture)
    {
        throw new Exception();
    }
}