简体   繁体   中英

Limit the Properties Bound to DataGrid in WPF using MVVM

All, a simple question. I have a MVVM application with a DataGrid which I have bound to a ViewModel using

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

where the Resources is defined via

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

In the ResourceViewModel class however, I not only have properties that I want to appear in the DataGrid , but other properties that I do not want to appear in the DataGrid . The ResourceViewmodel class is

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");
        }
    }
}

Where I don't want IsSelected to appear in the DataGrid and I want each item in ResourceStringList to appear in a different column of the Datagrid . My questions are:

1. How do I prevent IsSelected from showing [as a Checkbox ] in the DataGrid ?

2. How do I get the binding to the DataGrid to automatically display items in separate columns?

What have you tried:

  1. I have attempted to inherit from the ResourceViewmodel class and bind to this instead, but this is disgusting and I would like another more elegant solution; please :].

  2. I have no idea how to proceed with this one. The number of items stored in the List is variable and set at runtime - so this needs to be a List .

As always, thanks very much for your time.

I think the options are to turn off auto generation as Silvermind mentioned (ie setting DataGrid.AutoGenerateColumns to false and then defining the columns) or implement ITypedList. For example you could create a derived ObservableCollection that implements ITypedList and returns properties based on some attribute you put on the properties you want to hide.

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;
    }
}

To me its just easier not auto generate columns. But that's a personal preference, so I think the easiest way to not allow some properties to be exposed is to use the power of interfaces :)

  1. Bind to ObservableCollection of IResourceViewModel - make Resources property a list of interface instead of a concrete type
  2. make ResourceViewModel implement IResourceViewModel
  3. in IResourceViewModel remove the properties that you don't want to be visible to the grid from the interface

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM