绑定不会更新。 (父母的财产变更?!)

时间:2015-04-18 14:35:19

标签: c# wpf binding inotifypropertychanged

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

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>

如果我更改第一个TextBox的Text,则第二个TextBox不会更新。

我的转换器:

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

债券类:

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

的DataContext:

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

2 个答案:

答案 0 :(得分:1)

如果您使用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绑定使用control的DataContext。 DataContext通过可视树从上层元素(例如Window)传递到下层元素(例如TextBox)。

但这些建议无法解决您的问题。当您在第一个TextBox中更改X的值时,Position属性永远不会更改,因此不会调用RaisePropertyChanged,并且不会更新第二个TextBox X的新值。如果您希望TextBox的值均为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();
    }
}

答案 1 :(得分:0)

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

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

public RaPoint Position
{
   get; set;
}

接下来的事情是,您希望TextBox每当X更新Position时,理想情况下,您不希望仅仅DataContext绑定{{1}只会改变一次),你想绑定到Position.X,因为属性改变了事件的地方是。通过这样做,转换器将每次X更改时进行评估。你也想要只有Position类,在转换器中传递。您需要更新转换器,以便将Position传递给它。最简单的方法是使用MultiValuConverter传递给Parameter对象以及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();
    }
}