2010-06-30 16 views
8

CollectionViewSource'da saklanan ve DataGrid'a bağlı bir nesne koleksiyonum var. Şu anda DataGrid'da seçilen nesnenin 'ayrıntı görünümünü' görüntülemek istiyorum. Geçerli nesneyi CollectionViewSource.View.CurrentItem kullanarak edinebilirim. bu özelliklerin her birinin IsImportant özniteliği ile işaretlenmiş için ben yapmak istiyorum neWPF: Nesnenin özelliklerini (bazıları) bir nesnesine dinamik olarak bağlama

MyClass 
{ 
    [IsImportant] 
    AProperty{} 

    AnotherProperty{} 

    [IsImportant] 
    YetAnotherProperty{} 
} 

, bir liste kutusunda ekran (mülkiyet adıyla) bir etiket ve (düzenleme için) bir kontrolüdür. Bağlama, yapılan düzenlemeler, DataGrid ve destek nesnesi arasında çalışmalıdır. Görüntülenen denetim özelliği, boolean, string veya IEnumerable<string> veya (belirtilemez ve yeni satır sınırlandırılmış dizeleri dönüştürmek için bir IValueConverter yazmış olabilir) türüne göre değişebilir.

Bunu yapmak için bir yöntem bilen var mı? Şu anda aşağıda aracılığıyla her bir özellik değerlerini görüntüleyebilir, ancak düzenleme onları destek nesnesi güncelleme olmaz: elle özellik adları belirtmeden,

listBox.ItemsSource = from p in typeof(MyClass).GetProperties() 
         where p.IsDefined(typeof(IsImportant), false) 
         select p.GetValue(_collectionViewSource.View.CurrentItem, null); 

, netleştirmek için bu 'automagicallylar' olmasını istiyoruz XAML. Özniteliklerle işaretlenmiş özellikleri temel alarak çalışma zamanında XAML'ye dinamik olarak ekleyebiliyorsam, bu da iyi olur.

cevap

12

Sen özellik adı ve özellik değerini düzenlemek için kontrol ile bir etiketi olan bir kontrol isteyen, böylece denetim için DataContext olarak hareket etmek, belirli bir nesnenin özelliği sarar bir sınıf oluşturarak başlayın:

public class PropertyValue 
{ 
    private PropertyInfo propertyInfo; 
    private object baseObject; 

    public PropertyValue(PropertyInfo propertyInfo, object baseObject) 
    { 
     this.propertyInfo = propertyInfo; 
     this.baseObject = baseObject; 
    } 

    public string Name { get { return propertyInfo.Name; } } 

    public Type PropertyType { get { return propertyInfo.PropertyType; } } 

    public object Value 
    { 
     get { return propertyInfo.GetValue(baseObject, null); } 
     set { propertyInfo.SetValue(baseObject, value, null); } 
    } 
} 

bu kontroller ile doldurmak amacıyla bir nesneye bir ListBox ItemsSource bağlamak, böylece onun önemli özellikleri için ÖzellikDeğeri nesneler listesi bir nesneyi dönüştürür bir IValueConverter oluşturmak istiyorum:

public class PropertyValueConverter 
    : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return 
      from p in value.GetType().GetProperties() 
      where p.IsDefined(typeof(IsImportant), false) 
      select new PropertyValue(p, value); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return Binding.DoNothing; 
    } 
} 

Sonuncu numara Düzenleme denetiminin özellik türüne göre değişiklik göstermesini istemiş olmanızdır. Bunu ContentControl kullanarak ve ContentTemplate özelliğini özellik türüne bağlı olarak çeşitli düzenleyici şablonlarından birine ayarlayarak yapabilirsiniz. Sonra

<DataTemplate x:Key="CheckBoxTemplate"> 
    <CheckBox IsChecked="{Binding Value}"/> 
</DataTemplate> 
<DataTemplate x:Key="TextBoxTemplate"> 
    <TextBox Text="{Binding Value}"/> 
</DataTemplate> 
<Style x:Key="EditControlStyle" TargetType="ContentControl"> 
    <Setter Property="ContentTemplate" Value="{StaticResource TextBoxTemplate}"/> 
    <Style.Triggers> 
     <DataTrigger Binding="{Binding PropertyType}" Value="{x:Type sys:Boolean}"> 
      <Setter Property="ContentTemplate" Value="{StaticResource CheckBoxTemplate}"/> 
     </DataTrigger> 
    </Style.Triggers> 
</Style> 
<DataTemplate DataType="{x:Type local:PropertyValue}"> 
    <StackPanel Orientation="Horizontal"> 
     <Label Content="{Binding Name}"/> 
     <ContentControl Style="{StaticResource EditControlStyle}" Content="{Binding}"/> 
    </StackPanel> 
</DataTemplate> 

, sadece ListBox oluşturabilir: özellik bir Boole ve aksi bir TextBox ise bu örnek, bir CheckBox kullanır

<ItemsControl ItemsSource="{Binding Converter={StaticResource PropertyValueConverter}}"/> 
+0

O harika görünüyor; Bir şansım var ve onu nasıl yapacağını bildiğim kadarıyla uygulayacağım. Teşekkürler! –

+0

Bu, çoğunlukla harika çalışıyor. Bağlantının ilk ayarlandığı sırada boş bir nesne aldığı için PropertyValueConverter'e yeni bir denetim ekledim. Tek sorun şu ki, eğer bu kontrolde bir değeri değiştirirsem, datagrid'e yayılmaz. Değişen değer, itemscontrol tarafından hala gösterildiğinden, ancak kılavuza bildirilmediğinden muhtemelen yedekleme nesnesi değişiyor. Bu Binding.DoNothing ile ilgisi var mı? –

+1

@Daniel: Bir denetim tarafından yapılan güncellemelerin aynı mülke bağlı diğer denetimlere yansıtılmasını istiyorsanız, nesnenizin INotifyPropertyChanged öğesini uygulaması gerekir. Ayrıca, PropertyValue'da INotifyPropertyChanged uygulamasını da uygulamanız gerekir. PropertyValueConverter, tek yönlü olan ItemsSource bağlayıcısının kendisi içindir, bu yüzden ConvertBack çağrılmayacak ve Binding.DoNothing önemli olmayacaktır. – Quartermeister

İlgili konular