【问题标题】:Binding does not update. (Property change of Parent?!)绑定不更新。 (父母的财产变更?!)
【发布时间】:2015-06-25 10:55:22
【问题描述】:

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

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 的文本,第二个 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));
            }
        }
    }

数据上下文:

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

【问题讨论】:

    标签: c# wpf binding inotifypropertychanged


    【解决方案1】:

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

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

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

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

    但是这些建议并不能解决您的问题。当您在第一个 TextBox 中更改 X 的值时,Positionproperty 永远不会更改,因此不会调用 RaisePropertyChanged,并且不会使用 X 的新值更新第二个 TextBox。如果您希望拥有一个同时具有XY 值的TextBox,则使用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();
        }
    }
    

    【讨论】:

      【解决方案2】:

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

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

      public RaPoint Position
      {
         get; set;
      }
      

      接下来你希望TextBoxX 更新时更新,所以理想情况下,你不想简单地绑定到Position(因为DataContext 只会更改一次) ,您想绑定到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();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-16
        • 1970-01-01
        相关资源
        最近更新 更多