Reputation: 1627
I have a DataGrid
where the ItemSource
is an Observable Collection bound using MVVM
archetype. I would like to not show the ID property of the class displayed in my DataGrid
however I still need the property to exist.
My Code:
XAML
<DataGrid ItemsSource="{Binding MyData}" IsReadOnly="True" Name="dtSearch" />
View Model
private ObservableCollection<MyDataClass> myData;
public ObservableCollection<MyDataClass> MyData
{
get { return myData; }
set
{
myData= value;
RaisePropertyChanged("MyData");
}
}
Observable Class
public partial class MyDataClass
{
public int ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
Is there an attribute I can give my ID property to hide it from the DataGrid
?
Do I need to create another class for visible properties?
Upvotes: 6
Views: 7804
Reputation: 1
You can modify columns in the AutoGeneratedColumns
event of the DataGrid object.
You can rename them and remove those that you don't want to be displayed.
Upvotes: 0
Reputation: 31721
This issue will happen regardless of whether the data resides in an ObservableCollection
or not.
To correct this, one must set the grid to not auto generate the columns. That is done by setting the property AutoGenerateColumns=False
and then in the xaml specify the columns desired.
<DataGrid ItemsSource="{Binding MyData}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTextColumn Header="The Code"
Binding="{Binding Code}"/>
<DataGridTextColumn Header="The Name"
Binding="{Binding Name}"/>
<DataGridTextColumn Header="The Type"
Binding="{Binding Type}"/>
</DataGrid.Columns>
</DataGrid>
Check out more column options in the documentation for the DataGrid.
Upvotes: 9
Reputation: 205899
WPF data binding engine binds to all public properties of the object. So, the simplest is to make your ID property internal (if that doesn't break any other code).
However, there is a more general approach when binding to a list of objects. First, put the following in some common place:
public class BindableCollection<T> : ObservableCollection<T>, ITypedList
{
string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return null; }
PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
{
return TypeDescriptor.GetProperties(typeof(T), PropertyFilter);
}
static readonly Attribute[] PropertyFilter = { BrowsableAttribute.Yes };
}
and use that class instead of ObservableCollection<T>
. Then just use Browsable
attribute to hide members of the item class. For your example it's something like this:
View Model
private BindableCollection<MyDataClass> myData;
public BindableCollection<MyDataClass> MyData
{
get { return myData; }
set
{
myData= value;
RaisePropertyChanged("MyData");
}
}
Observable Class
public partial class MyDataClass
{
[Browsable(false)]
public int ID { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
Upvotes: 8
Reputation: 13188
XAML:
<DataGrid x:Name="dataGrid1" Margin="0" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
<DataGridTextColumn Binding="{Binding Code}" Header="Code"/>
<DataGridTextColumn Binding="{Binding Type}" Header="Type"/>
</DataGrid.Columns>
</DataGrid>
Code behind:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
ObservableCollection<MyDataClass> data = new ObservableCollection<MyDataClass>();
data.Add(new MyDataClass { Code = "Code 1", ID = 1, Name = "Name 1", Type = "Type 1" });
data.Add(new MyDataClass { Code = "Code 2", ID = 2, Name = "Name 2", Type = "Type 2" });
data.Add(new MyDataClass { Code = "Code 3", ID = 3, Name = "Name 3", Type = "Type 3" });
data.Add(new MyDataClass { Code = "Code 4", ID = 4, Name = "Name 4", Type = "Type 4" });
data.Add(new MyDataClass { Code = "Code 5", ID = 5, Name = "Name 5", Type = "Type 5" });
dataGrid1.ItemsSource = data;
}
Result:
Upvotes: 2