我有一个ItemsControl,它应该显示一个对象的某些属性的值。
ItemsControl的ItemsSource是一个具有两个属性的对象:实例和 PropertyName 。
我要做的是显示 Instance 对象的所有属性值,但是我找不到设置绑定路径到 PropertyName 价值:
<ItemsControl ItemsSource={Binding Path=InstanceProperties}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=PropertyName, Mode=OneWay}"/>
<TextBlock Text=": "/>
<TextBlock Text="{Binding Source=??{Binding Path=Instance}??, Path=??PropertyName??, Mode=OneWay}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
问号是我不知道如何创建绑定的点。
我最初尝试使用MultiValueConverter:
<TextBlock Grid.Column="1" Text="{Binding}">
<TextBlock.DataContext>
<MultiBinding Converter="{StaticResource getPropertyValue}">
<Binding Path="Instance" Mode="OneWay"/>
<Binding Path="PropertyName" Mode="OneWay"/>
</MultiBinding>
</TextBlock.DataContext>
</TextBlock>
MultiValueConverter使用Reflection查看 Instance 并返回属性的值。
但是如果属性值发生变化,则不会通知此更改,并且显示的值保持不变。
我正在寻找一种方法只使用XAML,如果可能的话,如果不是,我将不得不为ItemsSource集合的项目编写一个包装类,我知道如何做,但是,因为它将是我项目中的一项重复任务,它将非常昂贵。
对于那些提问者, InstanceProperties 是ViewModel上的一个属性,它公开了这样的对象集合:
public class InstanceProperty : INotifyPropertyChanged
{
//[.... INotifyPropertyChanged implementation ....]
public INotifyPropertyChanged Instance { get; set; }
public string PropertyName { get; set; }
}
显然,两个属性通知他们的值正在通过INotifyPropertyChanged进行更改,为简单起见,我没有包含OnPropertyChanged事件处理。
该集合中填充了一组有限的属性,我必须向用户提供这些属性,我无法使用PropertyGrid,因为我需要过滤我必须显示的属性,并且必须显示这些属性以图形丰富的方式。
由于
答案 0 :(得分:1)
好的,感谢@GazTheDestroyer评论:
@GazTheDestroyer 写道:我想不出任何方法只能在XAML中动态迭代和绑定到任意对象的属性。您需要编写VM或行为来执行此操作,以便您可以查看更改通知,但是使用反射以通用方式执行此操作,您可以在整个项目中重复使用
我找到了一个解决方案:像这样编辑ViewModel类 InstanceProperty
这是新的,完整的ViewModel类:
public class InstanceProperty : INotifyPropertyChanged
{
#region Properties and events
public event PropertyChangedEventHandler PropertyChanged;
private INotifyPropertyChanged FInstance = null;
public INotifyPropertyChanged Instance
{
get { return this.FInstance; }
set
{
if (this.FInstance != null) this.FInstance.PropertyChanged -= Instance_PropertyChanged;
this.FInstance = value;
if (this.FInstance != null) this.FInstance.PropertyChanged += Instance_PropertyChanged;
this.CheckProperty();
}
}
private string FPropertyName = null;
public string PropertyName
{
get { return this.FPropertyName; }
set
{
this.FPropertyName = value;
this.CheckProperty();
}
}
private System.Reflection.PropertyInfo Property = null;
public object PropertyValue
{
get { return this.Property?.GetValue(this.Instance, null); }
}
#endregion
#region Private methods
private void CheckProperty()
{
if (this.Instance == null || string.IsNullOrEmpty(this.PropertyName))
{
this.Property = null;
}
else
{
this.Property = this.Instance.GetType().GetProperty(this.PropertyName);
}
this.RaisePropertyChanged(nameof(PropertyValue));
}
private void Instance_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == this.PropertyName)
{
this.RaisePropertyChanged(nameof(PropertyValue));
}
}
private void RaisePropertyChanged(string propertyname)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
}
#endregion
}
这是XAML:
<ItemsControl ItemsSource={Binding Path=InstanceProperties}>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=PropertyName, Mode=OneWay}"/>
<TextBlock Text=": "/>
<TextBlock Text="{Binding Path=PropertyValue, Mode=OneWay}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
答案 1 :(得分:0)
无法绑定到Instance.PropertyName吗?