2013-05-21 145 views
1

所有这些都是一个简单的问题。我有使用使用MVVM限制WPF中绑定到DataGrid的属性

<DataGrid ItemsSource="{Binding Path=Resources}" ...></DataGrid> 

与我已绑定到一个ViewModel一个DataGrid一个MVVM应用,其中Resources经由

public ObservableCollection<ResourceViewModel> Resources { get; private set; } 

但是限定在ResourceViewModel类,我不仅有我想性质出现在DataGrid,但其他属性我想要出现在DataGrid。该ResourceViewmodel类是

public class ResourceViewModel : WorkspaceViewModel, IDataErrorInfo 
{ 
    readonly Resource resource; 
    readonly ResourceDataRepository resourceRepository; 
    private bool isSelected; 

    public ResourceViewModel(Resource resource, ResourceDataRepository resourceRepository) 
    { 
     if (resource == null) 
      throw new ArgumentNullException("resource"); 
     if (resourceRepository == null) 
      throw new ArgumentNullException("resourceRepository"); 
     this.resource = resource; 
     this.resourceRepository = resourceRepository; 
    } 

    public string KeyIndex 
    { 
     get { return this.resource.KeyIndex; } 
     set 
     { 
      if (value == this.resource.KeyIndex) 
       return; 
      this.resource.KeyIndex = value; 
      base.OnPropertyChanged("KeyIndex"); 
     } 
    } 

    public string FileName 
    { 
     get { return this.resource.FileName; } 
     set 
     { 
      if (value == this.resource.FileName) 
       return; 
      this.resource.FileName = value; 
      base.OnPropertyChanged("FileName"); 
     } 
    } 

    public List<string> ResourceStringList 
    { 
     get { return this.resource.ResourceStringList; } 
     set 
     { 
      if (Utilities.Utilities.ScrambledEquals<string>(this.resource.ResourceStringList, value)) 
       return; 
      this.resource.ResourceStringList = value; 
      base.OnPropertyChanged("ResourceStringList"); 
     } 
    } 

    public bool IsSelected 
    { 
     get { return isSelected; } 
     set 
     { 
      if (value == isSelected) 
       return; 
      isSelected = value; 
      base.OnPropertyChanged("IsSelected"); 
     } 
    } 
} 

在哪里我不想IsSelected出现在DataGrid,我想在ResourceStringList每个项目出现在Datagrid的不同列。我的问题是:

1.如何防止IsSelectedDataGrid中显示为[Checkbox]?

2.如何获取与DataGrid的绑定,以自动在单独列中显示项目?

你尝试过什么:

  1. 我试图从ResourceViewmodel类继承并绑定到这个代替,但是这是令人厌恶的,我想另一个更优雅的解决方案;请 :]。

  2. 我不知道如何继续这一个。存储在List中的项目数量是可变的,并且在运行时设置 - 因此这需要是List

一如既往,非常感谢您的时间。

+1

您可以手动创建自己的列的属性。有关更多信息,请参阅[DataGrid.AutoGenerateColumns](http://msdn.microsoft.com/zh-cn/library/system.windows.controls.datagrid.autogeneratecolumns.aspx)。 – Silvermind

+0

如果ResourceStringList中的项目数量对于每一行不同,您想要生成多少列,并且它们的头应该是什么? – LPL

+0

当人们在MVVM模式中使用ObservableCollection时,我总是感到困惑。如果你使用MVVM,我认为它不是必须的.​​.....我真的从不需要它,因为总是没有它的解决方案。 :/ –

回答

4

我认为这些选项是关闭自动生成Silvermind提到(即设置DataGrid.AutoGenerateColumns为false,然后定义列)或实现ITypedList。例如,您可以创建一个实现ITypedList的派生ObservableCollection,并根据您放入要隐藏的属性的某些属性返回属性。

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     this.DataContext = new TypedListObservableCollection<Foo>(); 

     InitializeComponent(); 
    } 
} 

public class TypedListObservableCollection<T> : ObservableCollection<T> 
    , ITypedList 
{ 
    public TypedListObservableCollection() 
    { 
    } 

    PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) 
    { 
     return TypeDescriptor.GetProperties(typeof(T), new Attribute[] { BrowsableAttribute.Yes }); 
    } 

    string ITypedList.GetListName(PropertyDescriptor[] listAccessors) 
    { 
     return typeof(T).Name; 
    } 
} 

public class Foo 
{ 
    public string Name 
    { 
     get; 
     set; 
    } 

    [Browsable(false)] 
    public bool IsSelected 
    { 
     get; 
     set; 
    } 
} 
+0

+1感谢您的帮助。你可以提供一些建议,告诉我如何使用我的'List ResourceStringList'中的条目填充'DataGrid'列,因为此时'DataGrid'只显示'(Collection)'列。有人提到,从列表获得的列会得到什么标题:有没有办法提供这个?非常感谢您的时间... – MoonKnight

+0

@LPL指出,如果ResourceStringList至少在理论上每个数据项可以有不同数量的项目并且必须定义列所有的项目?如果您知道项目的最大数量,并且希望为每个项目生成一列,那么理论上可以创建一个派生的PropertyDescriptor,它表示每个列,并返回从GetItemProperties返回的PropertyDescriptorCollection中的那些列。 – AndrewS

+0

我不知道如果DataGrid响应列添加/删除时,但如果是这样,你需要它,那么你需要编写自己的自定义IBindingList实现,并在添加/删除列时引发ListChanged。 – AndrewS

1

对我来说,它只是更容易不自动生成列。但是,这是个人喜好,所以我觉得不能让某些属性暴露的最简单的方法是使用接口的电源:)

  1. 绑定到IResourceViewModel的的ObservableCollection - 使资源属性界面的列表,而不是具体类型
  2. 化妆ResourceViewModel实施IResourceViewModel
  3. 在IResourceViewModel删除你不希望到电网可见从接口
+0

虽然这会限制属性,但它也意味着你不会自动添加新的功能(假设你想这样做),因为T不会是可创建的类型,所以你将不得不使用BindingList 并处理AddingNew或自己实现IEditableCollectionView或IBindingList。 – AndrewS

+0

是真实的(某一点 - 让事情开箱即用),这就是为什么我在发布我之前给你的答案+1的原因。然而,在视图模型中使用Add命令并处理列表操作也可以实现 –