我在更新绑定时遇到问题。 但我认为解释我的问题的最简单方法是我的代码:
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();
}
}
债券类别:
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);
}
}
如果要使用RaPoint
实例(Position
属性)设置 Window 的DataContext
,则应尝试以这种方式绑定:
<TextBox Text="{Binding Path=X, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Text="{Binding Converter={StaticResource PositionToStartPosition}, UpdateSourceTrigger=PropertyChanged}"/>
基本上,数据绑定在不同对象的两个属性之间建立连接。在第一行中,您将绑定在数据上下文中设置的对象的属性。Path
用于指定该对象的属性,或者可能指向属性的属性(假设 X 将具有属性 Z,然后您可以执行类似Path=X.Z
的操作)。
关于第二TextBox
,如果不指定绑定的Source
,Path
、RelativeSource
或ElementName
绑定使用控件的 DataContext。DataContext
通过可视化树从上层元素(例如窗口)传递到下层元素(在您的情况下TextBox
)。
但是这些建议并不能解决您的问题。当您更改第一个文本框中X
的值时,Position
属性永远不会更改,因此不会调用RaisePropertyChanged
,并且不会使用新值 X 更新第二个文本框。如果要使文本框同时具有值X
和Y
,请使用多重绑定。在窗口/用户控件中执行以下操作:
<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
永远不会更改,因此在 Position 属性的 setter 中设置RaisePropertyChnage
是没有意义的。删除它。
public RaPoint Position
{
get
{
return _Position;
}
set
{
_Position = value;
RaisePropertyChanged(PositionPropertyName);
}
}
自
public RaPoint Position
{
get; set;
}
接下来的事情是,您希望TextBox
在X
更新时更新,因此理想情况下,您不希望仅绑定到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();
}
}