我有一个WPF列表视图,显示一个材料,它的厚度,和一个单位的厚度在一个组合框…xaml看起来是这样的(为了清晰起见,我去掉了所有的可视化设置):
<ListView ItemsSource="{Binding Path=MaterialLayers}" IsSynchronizedWithCurrentItem="True">
<ListView.Resources>
<x:Array x:Key="DistanceUnitItems" Type="sys:String" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<sys:String>cm</sys:String>
<sys:String>inches</sys:String>
</x:Array>
<DataTemplate x:Key="ThicknessUnit">
<ComboBox ItemsSource="{StaticResource DistanceUnitItems}" SelectedIndex="{Binding ThicknessUnit}" />
</DataTemplate>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn Header="Material Name" DisplayMemberBinding="{Binding MaterialName}"/>
<GridViewColumn Header="Material Thickness" DisplayMemberBinding="{Binding MaterialThickness}"/> />
<GridViewColumn Header="Thickness Unit" CellTemplate="{StaticResource ThicknessUnit}" />
</GridView>
</ListView.View>
</ListView>
MaterialLayers
是ObservableCollection<MaterialLayer>
MaterialLayer有MaterialName, MaterialThickness和ThicknessUnit属性(0表示厘米,1表示英寸)。MaterialThickness将内部存储的值(以厘米为单位)转换为ThicknessUnit指定的单位。
当ThicknessUnit改变时,我的DataViewModel调用PropertyChanged
事件处理程序,以"MaterialLayers"作为属性名称。
所以,我希望当ThicknessUnit改变时,MaterialThickness自动更新。
我已经调试了它,并且PropertyChanged("MaterialLayers")被调用。(当ThicknessUnit set方法被调用时,它调用父数据类(MyData)上的事件,后者调用DataViewModel上的事件,后者调用PropertyChanged处理程序。)
DataViewModel的相关代码
public delegate void DataChangedHandler(String identifier);
public DataViewModel()
{
Data = new MyData();
Data.DataChanged += new DataChangedHandler(RaisePropertyChanged);
}
public ObservableCollection<XTRRAMaterialLayer> MaterialLayers
{
get { return _data.MaterialLayers; }
set { }
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
// take a copy to prevent thread issues
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
MyData的相关代码
public class XTRRAData
{
public ObservableCollection<XTRRAMaterialLayer> MaterialLayers { get; set; }
public event DataChangedHandler DataChanged;
public MyData()
{
MaterialLayers = new ObservableCollection<MaterialLayer>();
}
public void myDataChanged(String identifier)
{
DataChanged(identifier);
}
public void AddLayer()
{
MaterialLayer layer = new MaterialLayer() { MaterialName="Test", MaterialThickness=5, ThicknessUnit=0 };
layer.DataChanged += new DataChangedHandler(myDataChanged);
}
}
来自MaterialLayer的相关代码
public class XTRRAMaterialLayer
{
public XTRRAMaterialLayer()
{
_thicknessUnit = 0; // cm
}
public event DataChangedHandler DataChanged;
public String MaterialName { get; set; }
public double MaterialThickness
{
get
{
switch (_thicknessUnit)
{
default:
case 0:
return DIST;
case 1:
return DIST * 0.393700787;
}
}
set
{
switch (_thicknessUnit)
{
default:
case 0:
DIST = value;
break;
case 1:
DIST = value / 0.393700787;
break;
}
}
}
public int _thicknessUnit;
public int ThicknessUnit
{
get { return(int) _thicknessUnit; }
set
{
_thicknessUnit = (eThicknessUnits)value;
FireDataChanged("MaterialLayers");
}
}
public void FireDataChanged(String identifier)
{
if(DataChanged!=null)
{
DataChanged(identifier);
}
}
}
有人能帮忙吗?
你需要实现INotifyPropertyChanged在类中,你正在改变的属性是-在你的情况下XTRRAMaterialLayer,并引发PropertyChanged事件时,属性的变化。
你的属性应该看起来像这样:
public int ThicknessUnit
{
get { return(int) _thicknessUnit; }
set
{
_thicknessUnit = (eThicknessUnits)value;
NotifyPropertyChanged();
}
}
NotifyPropertyChanged事件处理程序:
public event PropertyChangedEventHandler PropertyChanged;
// This method is called by the Set accessor of each property.
// The CallerMemberName attribute that is applied to the optional propertyName
// parameter causes the property name of the caller to be substituted as an argument.
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}