단순한 컬렉션을 내부 개체로 사용하는 대신 컬렉션에서 파생 된 클래스를 만들고 ICustomTypeDescriptor
을 구현하십시오. 인터페이스 구현에서 컬렉션의 요소를 반복하고 이에 따라 속성 설명자 컬렉션을 채 웁니다. 일단 그렇게하면 XAML의 속성에 바인딩 할 수 있어야합니다.
예 - 당신은 키 이름 (내가 한 줄에 압축 된 모든 사소한 메소드 구현)에 결합 할 수있는 사전을 기반으로 데이터 객체 : 뒤에 코드에서
class DictionaryDataObject : Dictionary<string, object>, ICustomTypeDescriptor
{
#region ICustomTypeDescriptor Members
public AttributeCollection GetAttributes() { return AttributeCollection.Empty; }
public string GetClassName() { return "DictionaryDataObject"; }
public string GetComponentName() { return null; }
public TypeConverter GetConverter() { return null; }
public EventDescriptor GetDefaultEvent() { return null; }
public PropertyDescriptor GetDefaultProperty() { return null; }
public object GetEditor(Type editorBaseType) { return null; }
public EventDescriptorCollection GetEvents(Attribute[] attributes) { return EventDescriptorCollection.Empty; }
public EventDescriptorCollection GetEvents() { return EventDescriptorCollection.Empty; }
public PropertyDescriptorCollection GetProperties() { return GetProperties(null); }
public object GetPropertyOwner(PropertyDescriptor pd) { return this; }
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
var pds =
this.Keys
.Select(x => new DictionaryPropertyDescriptor(x))
.ToArray();
return new PropertyDescriptorCollection(pds);
}
#endregion
}
class DictionaryPropertyDescriptor : PropertyDescriptor
{
public DictionaryPropertyDescriptor(string name) : base(name, null) { }
public override bool CanResetValue(object component) { return false; }
public override Type ComponentType { get { return null; } }
public override bool IsReadOnly { get { return false; } }
public override Type PropertyType { get { return typeof(object); } }
public override void ResetValue(object component) { }
public override bool ShouldSerializeValue(object component) { return false; }
public override object GetValue(object component)
{
var dic = component as DictionaryDataObject;
if (dic == null) return null;
return dic[Name];
}
public override void SetValue(object component, object value)
{
var dic = component as DictionaryDataObject;
if (dic == null) return;
dic[Name] = value;
}
}
샘플 객체 설정 :
DictionaryDataObject ddo = new DictionaryDataObject();
public Window4()
{
ddo["propa"] = 1;
ddo["propb"] = "foo";
ddo["propc"] = "bar";
ddo["propd"] = 4.5;
InitializeComponent();
DataContext = ddo;
}
XAML 사용 : 당신이 ADAP하려는 경우
<Window.Resources>
<DataTemplate x:Key="template">
<WrapPanel>
<TextBlock Text="{Binding propa}" Margin="5"/>
<TextBlock Text="{Binding propb}" Margin="5"/>
<TextBlock Text="{Binding propc}" Margin="5"/>
<TextBlock Text="{Binding propd}" Margin="5"/>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource template}"/>
</Grid>
이 솔루션을 사전 대신 목록에 추가하려면 목록 요소의 일부 속성을 기반으로 각 속성 이름을 설정해야합니다.
나는 읽기가 있었고 그 해결책은 정말 우아한 것처럼 보였다. 템플릿 문자열에서했던 것처럼 컬렉션에 바인딩 할 수 있다는 것을 몰랐습니다. 즉 Text = '{{바인딩 기간 [{0}]. {1}}}' WPF로 제한되어 Silverlight에서 그럴 수 없다고 생각했습니다. 나는 더 조사 할 것이다. 감사! –