Hi, I am developing a WPF Application using MVVM pattern. I m attaching the final output which is required named "Final output required.jpg" and also what I am currently getting named "GridView xaml.png".
I need to display data in a grid where the columns are dynamic. So in order to achieve that I had created two classes, one named rows and other one columns. Finally I bind the collection containing rows with the GridView. My code sample is as follows:
//Observable property to bind with
public
ObservableCollection<Row> GridRows
{
get
{
return
_gridRows; }
set
{
_gridRows = value;
RaisePropertyChanged(() => GridRows);
}
}
//Rad Grid
public
class
Grid
{
public
Grid(){
Rows =
new
List<Row>();
}
//contains mutiple row
public
List<Row> Rows {
get
;
set
; }
}
// RadGrid Row
public
class
Row
{
public
Row()
{
Columns =
new
List<Column>();
}
// Row Name
public
string
RowName {
get
;
set
; }
//each row contains multiple columns
public
List<Column> Columns{
get
;
set
;}
}
//Rad Grid Column
public
class
Column {
public
string
ColumnName {
get
;
set
;}
public
int
Value {
get
;
set
; }
}
public
void
LoadData()
{
Grid table =
new
Grid();
for
(
int
i = 1; i < 11; i++)
{
Row row =
new
Row();
row.RowName =
"Row_"
+ i;
for
(
int
j = 0; j < 5; j++)
{
Column Column =
new
Column
{
ColumnName =
"Row_"
+ i +
"Col_"
+ j,
Value = i + j
};
row.Columns.Add(Column);
}
table.Rows.Add(row);
}
GridRows =
new
ObservableCollection<Row>(table.Rows);
}
The View for this is as follows:
<
telerik:RadGridView
Name
=
"GridView"
CanUserReorderColumns
=
"False"
CanUserSortColumns
=
"False"
ItemsSource
=
"{Binding GridRows}"
GridLinesVisibility
=
"Both"
AutoGenerateColumns
=
"True"
>
<
telerik:RadGridView.Columns
>
<!-- My question is how can i bind the dynamic columns here -->
<!-- I want to generate the columns spcified for each row -->
<
telerik:GridViewColumn
Header
=
"{Binding Name}"
>
<
telerik:GridViewColumn.CellTemplate
>
<
DataTemplate
>
<
TextBlock
Text
=
"{Binding Value}"
/>
</
DataTemplate
>
</
telerik:GridViewColumn.CellTemplate
>
</
telerik:GridViewColumn
>
</
telerik:RadGridView.Columns
>
</
telerik:RadGridView
>
Basically what my requirement is to create dynamic columns as per the Collection of column in Rows. . I tried but it's showing Collection in column.
Also i want to inline editing for columns that why using the GridView. Please check the required output and suggest if there is any other i can use .
Please response soon as i'm in rush .Also let me know if anything not clear.
Thanks
23 Answers, 1 is accepted
May I suggest you a slightly different approach for this scenario. It consist of using the ExpandoObject class, as you need to define dynamic columns. Using your current data structure, the ExpandoObject will serve as a proxy class, so that RadGridView can "understand" to what data type it is bound to.
First, you will have to define a property for the ItemsSource of RadGridView of type ObservableCollection<IDictionary<string, object>>. Each IDictionary would represent a row, where its Key is the name of a given column and its Value is the cell content.
Then you will need to iterate over your data structure and add the needed columns to each ExpandoObject and finally add it to aforementioned ObservableCollection. You can check the code snippet below illustrating a similar implementation
ObservableCollection<IDictionary<
string
,
object
>> collection =
new
ObservableCollection<IDictionary<
string
,
object
>>();
foreach
(var row
in
Grid.DataRows)
{
var expando = (IDictionary<
string
,
object
>)
new
ExpandoObject();
foreach
(var item
in
row.DataItems)
{
if
(!expando.ContainsKey(item.Column.ColumnName))
{
expando.Add(item.Column.ColumnName, item.Value);
}
}
collection.Add(expando);
}
Let me know should you need any further assistance.
Best Regards,
Stefan
Telerik
Could you please help us to achieve the below output using code behind C# wpf.
Hello Stefan,
is there a way to get RadDataFilter properly work with your solution? RadDataFilter only gives me Equal, Is Not Equal, Is Null, Is Not Null filtering options. This is probably due to it not knowing the exact data type of the columns.
Thank you for your help.
Niels
I am afraid that this behavior would be expected. The data engine of RadDataFilter adds its filter operators based on whether a given data type is a string or a numeric type. Note, that the dynamic type in most cases is treated as it has type object. You can take a look at the Using Type dynamic article for more information.
So, in such scenarios only the default filter operators are being added and unfortunately, providing a workaround for this scenario would not be possible.
Feel free to contact us should you have any other questions on our controls.
All the best,
Stefan X1
Telerik
Hi telerik,
We need to put a nested groups with dynamic header and subheaders and data.
We have a class with all the nested groups with dynamic header and subheaders and data..But we are unable to create a wpf nested group radgridview. Please help us to acheive the output.
The Columns and ColumnGroups properties of RadGridView are not dependency properties, thus you would not be able to bind them directly to the view model. Moreover, they do not expose a public setter. So, a possible solution would be to implement an attached behavior and handle the required operations through it.
I hope this helps.
Regards,
Stefan X1
Telerik by Progress
Hi!
I need to customize cells by cells dataContext.
I have dataTempate
<DataTemplate x:Key="TelerikValueNullableView">
<foc:ErrorInfoContentControl Style="{StaticResource ColumnErrorStyle}"
Visibility="{Binding IsDataSeriesEmpty, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
Validation.ErrorTemplate="{StaticResource ErrorInfoControlEntityErrorTemplate}"
ErrorInfoSourcePath="{Binding ValueDouble}">
<Border BorderThickness="2 0 0 0"
Visibility="{Binding Path=IsDataSeriesEmpty, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
Style="{StaticResource CellRowViewBorderStyle}">
<telerik:RadMaskedNumericInput DataContext="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type telerik:GridViewCell}}}"
Mask="#9.3"
IsReadOnly="True"
TextMode="PlainText"
UpdateValueEvent="LostFocus"
Validation.ErrorTemplate="{x:Null}"
Visibility="{Binding IsDataSeriesEmpty, Converter={StaticResource InverseBooleanToVisibilityConverter}}"
Style="{StaticResource CellRowTextViewStyleTelerik}"
Value="{Binding ValueDouble}" />
</Border>
</foc:ErrorInfoContentControl>
</DataTemplate>
But this dataContext contain Row DataContext by default, and I cant find Data for concrete cells. To solve this problem I written CellTemplateSelector. This Selector contain specific FIeldName for getting Data for concrete Cell.
public class CellTemplateSelector : System.Windows.Controls.DataTemplateSelector
{
private string _field;
private object _cellDataContext;
private DataTemplate _template;
public CellTemplateSelector(string field, DataTemplate template)
{
_field = field;
_template = template;
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var cell = (container as GridViewCell);
_cellDataContext = (item as IGetObjectByField).GetObject(_field);
if (_cellDataContext != null)
{
cell.DataContext = _cellDataContext;
return _template;
}
else
return base.SelectTemplate(item, container);
}
}
But if i change DataCOntext in CellTemplateSelector - somting going wrong, and cells work uncorrectly(f.e. dont out from editing mode).
Can you provide another solution for problem of getting DataContext for Cell, not for Row (inside dataTemplate for cell).
Generally speaking, RadGridView and its CellTemplateCelector mechanism are not meant to be used in such manner. Also, this seems to differentiate from the topic regarding which this thread was initially opened. Note, that we try to keep our support discussions consistent. With this in mind, I would kindly encourage you to open a new support thread and describe your requirement in it and the need to set the DataContext of the cell in such manner.
Thank you in advance for your cooperation.
Regards,
Stefan X1
Telerik by Progress
Can you please clarify whether you are using the RadGridView or RadComboBox component? Generally speaking, we do not have examples for ExpandoObject in particular, but we have a demo with DynamicObject implementation for RadGridView. It is demonstrated in the Binding to Dynamic Data topic and in the Binding to DynamicObject SDK Example. It can be reviewed through the SDK Samples Browser. The approach for using an ExpandoObject should be basically the same. Can you please check this out?
Regards,
Stefan
Progress Telerik
Hello Telerik team,
is there any demo code for binding RadGridview with dynamic column?
All examples discussed in the previously referred article are following the MVVM paradigm. Can you please take a look at it? Do you meet any specific difficulties with these examples?
Regards,
Stefan
Progress Telerik
Hi Stefan,
Please see the codes below. I have modified your code.
It is possible to assign custom object to the field where item.value is.
If possible how a property in custom object is bound to grid.
ObservableCollection<IDictionary<string, object>> collection =
new ObservableCollection<IDictionary<string, object>>();
foreach (var row in Grid.DataRows)
{
var expando = (IDictionary<string, object>)new ExpandoObject();
foreach (var item in row.DataItems)
{
question q1 = new question() {id = 1, value="A"}
if (!expando.ContainsKey(item.Column.ColumnName))
{
expando.Add(item.Column.ColumnName, q1);
}
}
collection.Add(expando);
}
public class question : ViewModelBase
{
public string id {get; set;}
public string value
{get;
set;
}
}
I am afraid that such nested binding would not be possible to be defined. The data can be populated and edited, but non of the data operations(such as sorting and filtering, for example) would be able to work as expected.
Regards,
Stefan
Progress Telerik
Dear Stefan,
You are right. as you said, we need to do a dynamic binding for un-forecast number of columns. Therefore, some default operations are damaged such sorting in my case. How can we fix it? How can we recover sorting? it is throwing an error from system (mscorlib)
I attached a pic for you to see the stacktrace
I can confirm that in case of such nested binding as discussed in my previous post the data operations would not be able to work. From the provided image I assume that the LINQ(on which RadGridView depends for processing its data operation) raises the exception. Although I am not aware of the specific setup you are using, please take a look at the previously referred Binding to Dynamic Data article and examples as the recommended and supported approaches are demonstrated in them.
Regards,
Stefan
Progress Telerik
Hi, I was hoping you could point me towards a sample that covers some simple column customization for a dynamically bound grid? Such as hiding a specific column or controlling the column width? If there is no sample can you recommend a way to address that?
Thanks
Manipulating the columns in such manner is irrelevant to whether the bound data source is dynamic or not. You can access and set the needed properties are demonstrated in the Defining Columns and Customizing Columns help articles. Can you please take a look at them?
Regards,
Stefan
Progress Telerik
Thanks Stefan,
I'm fairly new to WPF, only a couple months into it so there's a good chance my questions are not even on the right track but I can't seem to use any of the suggested approaches to customizing my columns.
I am using the BindingToICustomTypeDescriptor_WPF as my learning sample, I don't think I can use annotations because I don't know the column names or column number at design time. The grid will have some subset of cells always present, like the unique ID of the row,. I also can not use any approach the uses code behind in the xaml.cs file, I have to specify the column customization in either my viewmodel using some kind of attribute metadata, or in the xaml file.
Using the example from the Demo code in BindingToICustomTypeDescriptor_WPF project, lets say I want to Hide the Name column, and format the Established column
MyDataRow row = new MyDataRow();
row.AddPropertyValue("Name", "Liverpool");
row.AddPropertyValue("StadiumCapacity", 45362);
row.AddPropertyValue("Established", new DateTime(1892, 1, 1));
items.Add(row);
I don't know if I'm correct but I think one approach is to use some kind of template, like in my ex. below, I just haven't hit of a way to make this work.
something quick like this would work for the time being until I get a better grasp of WPF :)
<Window.Resources>
<local:MyViewModel x:Key="MyViewModel"/>
<Style x:Key="GridViewHeaderCellStyle" TargetType="telerik:GridViewHeaderCell">
<Setter Property="Width" Value="200"/>
</Style>
<Style x:Key="GridViewColumnStyle" TargetType="telerik:GridViewColumn">
<Setter Property="IsVisible" Value="False"/>
</Style>
</Window.Resources>
<Grid DataContext="{StaticResource MyViewModel}">
<telerik:RadGridView ItemsSource="{Binding Data}"
AutoGenerateColumns="True"
GroupRenderMode="Flat"
Margin="5" >
<telerik:RadGridView.Columns >
<telerik:GridViewDataColumn Header="ID"
DataMemberBinding="{Binding Name}"
Style="{StaticResource GridViewColumnStyle}" />
</telerik:RadGridView.Columns>
</telerik:RadGridView>
</Grid>
Maybe a better approach would be instead of adding a string to add a custom object that has attributes like isVisible or Width, set on the actual dynamically added object.. that was the sample code I was hoping to find, I looked through the 3 samples on dynamic bindings in the grid (BindingToDynamicObject, BindingToICustomTypeDescriptor, BindingToICustomTypeProvider), but non of these samples involves column styling
Thank you again
Chris
Thank you for the provided code snippets.
Please, note that adding styles that target the RadGridView columns such as GridViewColumn is not recommended since the columns are not actually visual elements.
That said, if the columns are defined in xaml, you can set the IsVisible property directly like so:
<telerik:GridViewDataColumn IsVisible=
"False"
/>
If the columns are dynamically generated, and you cannot use the xaml.cs file, you can handle the AutoGeneratingColumn event with a command from your viewmodel with our EventToCommandBehavior. In that event you have access to the dynamically generated columns and you can set their properties such as IsVisible or Width.
Hope you find this helpful.
Regards,
Vladimir Stoyanov
Progress Telerik
Hi Team,
Can please help us to bind checkbox control to columns values(true/false). I have attached screenshot.
I have values in code behind:
var row = new MyDataRow();
foreach (var row in rows)
{
var row = new MyDataRow();
foreach (var user in getUsers)
{
row[string.Format("User1")] = true;
row[string.Format("User2")] = true;
row[string.Format("User3")] = false;
}
data.Add(row);
}
Thank you for the provided picture.
Please, check out the attached sample project which demonstrates how to achieve the desired requirement.
Hope you find it helpful.
Regards,
Vladimir Stoyanov
Progress Telerik