Programmatically binding TreeViewItem to List of custom object - c#

How I can set programmatically Binding "Header" property of newTableList.Items elements to TableModel.TABLE_NAME ?
foreach (SchemaModel schema in connection.schemas)
{
TreeViewItem newSchema = new TreeViewItem()
{
Header = schema.SCHEMA_NAME.ToString()
};
Binding newTableBinding = new Binding();
newTableBinding.Source = schema.tables;
TreeViewItem newTableList = new TreeViewItem()
{
Header = "Tables",
};
BindingOperations.SetBinding( newTableList, TreeViewItem.ItemsSourceProperty, newTableBinding);
newSchema.Items.Add(newTableList);
newTVI.Items.Add(newSchema);
}
My old, very slow code looks like that:
foreach (TableModel table in schema.tables)
{
newTableList.Items.Add(new TreeViewItem()
{
Header = table.TABLE_NAME.ToString()
});
}
OLD TOPIC ( FOR BETTER VIEW )
I try to build custom TreeView and change my "VERY SLOW METHOD" with fastest with Binding to list of custom objects.
I have SchemaModel which contains
List<TableModel> tables
and every TableModel have
string TABLE_NAME.
My previous very slow method Was :
/* VERY SLOW METHOD !!! */
//foreach (TableModel table in schema.tables)
//{
// newTableList.Items.Add(new TreeViewItem()
// {
// Header = table.TABLE_NAME.ToString()
// });
//}
Creating each time TreeViewItem is slowing my UI which I cannot repair with multitasking.
I decided to programmatically Bind to list of TableModels like that :
Binding newTableBinding = new Binding();
newTableBinding.Source = schema.tables;
TreeViewItem newTableList = new TreeViewItem()
{
Header = "Tables",
// ItemsSource = schema.tables // also works
};
BindingOperations.SetBinding( newTableList, TreeViewItem.ItemsSourceProperty, newTableBinding);
How Can i Bind the Header property to "TABLE_NAME" for Items based on schema.tables list?
My full code
Code:
foreach (ConnectionModel connection in aliases)
{
TreeViewItem newTVI = new TreeViewItem() { Header = connection.alias.ToString() };
foreach (SchemaModel schema in connection.schemas)
{
TreeViewItem newSchema = new TreeViewItem() { Header = schema.SCHEMA_NAME.ToString() };
Binding newTableBinding = new Binding();
newTableBinding.Source = schema.tables;
// newTableBinding.Path = new PropertyPath("TABLE_NAME");
TreeViewItem newTableList = new TreeViewItem()
{
Header = "Tables",
// ItemsSource = schema.tables
};
BindingOperations.SetBinding( newTableList, TreeViewItem.ItemsSourceProperty, newTableBinding);
TreeViewItem newIndexList = new TreeViewItem() { Header = "Indexes" };
/* VERY SLOW METHOD !!! */
//foreach (TableModel table in schema.tables)
//{
// newTableList.Items.Add(new TreeViewItem()
// {
// Header = table.TABLE_NAME.ToString()
// });
//}
newSchema.Items.Add(newTableList);
newSchema.Items.Add(newIndexList);
newTVI.Items.Add(newSchema);
}
tmpAliasTree.Items.Add(newTVI);
}
tmpAliasTree is my TreeView.
My ConnectionModel
[Serializable()]
public class ConnectionModel
{
private int _id;
private string _dsn;
private string _alias ;
private string _host ;
private string _port ;
private string _database;
private string _username;
private string _password;
public List<SchemaModel> schemas = new List<SchemaModel>();
}
My SchemaModel :
[Serializable()]
public class SchemaModel
{
[System.Xml.Serialization.XmlElement("SCHEMA_NAME")]
public string SCHEMA_NAME { get; set; } = "";
[XmlArray("tables"), XmlArrayItem("TableModel", typeof(TableModel), ElementName = "TableModel")]
public List<TableModel> tables = new List<TableModel>();
}
My TableModel
[Serializable()]
public class TableModel
{
[System.Xml.Serialization.XmlElement("TABLE_CAT")]
public string TABLE_CAT { get; set; } = "";
[System.Xml.Serialization.XmlElement("TABLE_SCHEM")]
public string TABLE_SCHEM { get; set; } = "";
[System.Xml.Serialization.XmlElement("TABLE_NAME")]
public string TABLE_NAME { get; set; } = "";
[System.Xml.Serialization.XmlElement("TABLE_TYPE")]
public string TABLE_TYPE { get; set; } = "";
[System.Xml.Serialization.XmlElement("REMARKS")]
public string REMARKS { get; set; } = "";
}
Thank You for any advise.

Although I agree that you should consider moving your view definition to XAML, you can achieve what you're asking by utilizing ItemsControl.ItemContainerStyle property (both TreeView and TreeViewItem derive from ItemsControl). Basically, you need to define a style targeting TreeViewItem and add a setter for TreeViewItem.HeaderProperty with value holding an appropriate binding, and then assign that style either to your tree view, or particular items (depending on your needs). Here's an example:
TreeViewItem newTVI = new TreeViewItem() { Header = connection.alias.ToString() };
var tableModelItemStyle = new Style(typeof(TreeViewItem));
tableModelItemStyle.Setters.Add(new Setter
{
Property = TreeViewItem.HeaderProperty,
//since items will present instances of TableModel, the DataContext will hold
//the model, so we can define the binding using only the property name
Value = new Binding("TABLE_NAME"),
});
foreach(...)
{
...
TreeViewItem newTableList = new TreeViewItem
{
...
ItemContainerStyle = tableModelItemStyle,
};
...
}
If you want to set the style for all items in the tree view (which I do not recommend), you can do it like so:
newTVI.ItemContainerStyle = tableModelItemStyle;

Related

Binding List of Lists to DataGridView

For my current problem I want to create a DataGridView and use a list of objects as the datasource.
The problem I'm having is that the objects itself contains two lists, which are supposed to fill combobox columns. The DataGridView should contain three columns, each corresponding to my sample object below. The first column is a simple text column, while the other two are combo box columns.
Currently I'm receiving the error:
System.ArgumentException: The value DataGridViewComboBoxCell is invalid.
I've been looking for other solutions on SO, but can't seem to get it right.
public class SampleObject
{
public SampleObject(string name, IList<TimeSpan> startTimes, IList<Activity> completedActivities)
{
this.Name = name;
this.StartTimes = startTimes;
this.CompletedActivities = completedActivities;
}
public string Name { get; }
public IList<TimeSpan> StartTimes { get; }
public IList<Activity> CompletedActivities { get; }
}
Activity object:
public class Activity
{
public Activity(string activityName)
{
ActivityName = activityName;
}
public string ActivityName { get; }
public override string ToString()
{
return ActivityName;
}
}
And the code for adding the columns to my grid:
private void FillGrid()
{
sampleGrid.AutoGenerateColumns = false;
var columnName = new DataGridViewTextBoxColumn
{
DataPropertyName = nameof(SampleObject.Name),
HeaderText = "Name",
Width = 160,
ReadOnly = true
};
sampleGrid.Columns.Add(columnName);
var columnStartTimes = new DataGridViewComboBoxColumn()
{
ValueType = typeof(TimeSpan),
HeaderText = "StartTimes",
Width = 120,
ReadOnly = false
};
sampleGrid.Columns.Add(columnStartTimes);
var columnCompletedActivities = new DataGridViewComboBoxColumn
{
ValueType = typeof(Activity),
HeaderText = "Completed activities",
Width = 120,
ReadOnly = false
};
sampleGrid.Columns.Add(columnCompletedActivities);
}
And populating the grid:
List<SampleObject> myObjects = GetSampleObjectsBasedOnValue(value);
sampleGrid.DataSource = myObjects;
FillComboBoxesInDGV(myObjects);
Method for filling the comboboxes:
private void FillComboBoxesInDGV(IList<SampleObject> sampleObjects)
{
for (int i = 0; i < sampleObjects.Count; i++)
{
DataGridViewRow row = sampleGrid.Rows[i];
var firstBox = row.Cells[1] as DataGridViewComboBoxCell;
firstBox.DataSource = sampleObjects[i].StartTimes;
var secondBox = row.Cells[2] as DataGridViewComboBoxCell;
secondBox.DataSource = sampleObjects[i].CompletedActivities;
}
}
I still not sure why you do not keep the original IList<string> CompletedActivities instead of introducing the Activity class? Using the list in this manner worked in my tests.
However, since you did use the class Activity, I would assumed it would work as expected. However, I ran into the same issue you described. After some hair pulling (and I don’t have much), I found some help from the SO post… DataGridViewComboBoxCell Binding - “value is not valid” … this was not obvious to me and I am guessing you also, thinking that overriding the Activity class’s ToString method would be enough. This is obviously not the case.
It appears that setting the DataGridViewComboBoxColumns’s ValueMember property to the name of the property in the Activity class should eliminate the error.
var columnCompletedActivities = new DataGridViewComboBoxColumn {
HeaderText = "Completed activities",
ValueMember = "ActivityName",
Width = 120,
};
sampleGrid.Columns.Add(columnCompletedActivities);
I hope this works for you.

How to let a wpf datagrid generate columns dynamically based on the content of a list?

I have a collection of objects and each object contains a property of the type collection. My goal is to generate dynamically the datagrid columns based on the collection content and generate also the columns for the remaining properties, which are base types. It is important that a bool is displayed as a CheckBox.
My problem is: The resulting cell content of the dynamically generated columns would be an object (Trait in my object structure), and I want one of this objects properties to be displayed (Trait.Value). When I change content of a cell, the object behind should update.
I thought of a DataTable, but when I add a row I need the column key and the value. When I set the value to a custom object, I couldn't see any possibility to display and edit a single property of the custom object.
Second approach would be using dynamic objects, like in the following article:
Auto-Generating DataGrid Columns From DynamicObjects
, but I see the same proplem like DataTable
Additional Information:
I am using mvvm (when it's necessary I would break this pattern)
the datagrid should be editable
My object structure:
public class Model
{
//ItemsSource
public ObservableCollection<Person> Persons { get; set; }
}
public class Person
{
public string Name { get; set; }
//Generate Treats.Count columns
public ObservableCollection<Treat> Treats { get; set; }
}
public class Treat
{
//column header name
public string Name { get; set; }
//value that should be displayed
public string Value { get; set; }
}
My ViewModel.cs with sample data:
public class ViewModel
{
public Model Model { get; set; }
public ViewModel()
{
#region Sample Data
Model = new Model()
{
Persons = new ObservableCollection<Person>()
{
new Person()
{
Name = "Peter",
Treats = new ObservableCollection<Treat>()
{
new Treat()
{
Name = "Look1",
Value = "Nice"
},
new Treat()
{
Name = "Look2",
Value = "Super Nice"
}
}
},
new Person()
{
Name = "Manuel",
Treats = new ObservableCollection<Treat>()
{
new Treat()
{
Name = "Look1",
Value = "Bad"
},
new Treat()
{
Name = "Look2",
Value = "Super Bad"
}
}
}
}
};
#endregion
}
}
Information to class Model.cs:
property Persons is the binding collection, which should be used as the ItemsSource
the columns of the datagrid should be generated based on the object Person. One column for the Name and n columns for the collection Treats.
The result based on my sample data is something like this:
Since, you have said you are okay to break MVVM pattern, please try the below approach.
OVERVIEW:
Create a IvalueConverter to convert your itemsource to list of expandoobejcts
In Code behind of the DataGrid (Loaded Event or SourceChanged event), add a code to generate columns manually
CODES:
Create Converter: PART 1 First we need to get the List of all possible columsn that might pop in (since we don't know the collections yet)
ObservableCollection<Person> inputlist = (ObservableCollection<Person>)value;
List<string> PossibleColumnList = new List<string>();
PossibleColumnList.Add(nameof(Person.Name)); //since we need name header first.
List<string> TempColumnList = new List<string>();
foreach (Person P in inputlist)
{
foreach(Treat T in P.Treats)
{
if (TempColumnList.Contains(T.Name) == false) TempColumnList.Add(T.Name);
}
}
TempColumnList.Sort();
PossibleColumnList.AddRange(TempColumnList); //This way we get Name first and rest of the columns in sorted out manner
Create Converter: PART 2. Now create an IDictionary Object with all available colum headers
IDictionary<string, object> ColumnHeaderDictionary = new Dictionary<string, object>();
foreach (string columnheader in PossibleColumnList)
{
if (ColumnHeaderDictionary.ContainsKey(columnheader) == false) ColumnHeaderDictionary.Add(columnheader, new object());
}
Create Converter: PART 3 Now iterate through all persons and create a IDictionary for each person model. Convert idictionary to expando object and store in final list
List<ExpandoObject> FinalList = new List<ExpandoObject>();
foreach (Person p in inputlist)
{
ExpandoObject tempExpando = new ExpandoObject();
IDictionary<string, object> TempDictionary = tempExpando as IDictionary<string, object>;
foreach (var kvp in ColumnHeaderDictionary)
{
TempDictionary.Add(kvp);
}
TempDictionary[nameof(Person.Name)] = p.Name;
foreach(Treat t in p.Treats)
{
TempDictionary[t.Name] = t.Value;
}
FinalList.Add(tempExpando);
}
return FinalList;
XAML CODE:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid x:Name="grdMain" DataContext="{Binding}">
<DataGrid x:Name="dgMain" ItemsSource="{Binding ElementName=grdMain,Path=DataContext.Model.Persons,Converter={StaticResource NewConverter}}" Loaded="dgMain_Loaded" />
</Grid>
CODE BEHIND: TO MANUALLY CREATE COLUMNS
private void dgMain_Loaded(object sender, RoutedEventArgs e)
{
DataGrid workinggrid = sender as DataGrid;
ExpandoObject SingleExpando = (workinggrid.ItemsSource as List<ExpandoObject>).FirstOrDefault();
if (workinggrid == null) workinggrid = new DataGrid();
List<string> ColumHeaders = (SingleExpando as IDictionary<string, object>).ToList().Select(p => p.Key).ToList();
foreach (string ColumnName in ColumHeaders)
{
var newcolumn = new DataGridTextColumn() { Header = ColumnName, Binding = new Binding(ColumnName) };
workinggrid.Columns.Add(newcolumn);
}
}
FINAL OUTPUT:

Implementing Xamarin Forms context actions

I am trying to implement context actions on my list in Xamarin Forms but can't get it to work.
I am not using XAML, but instead creating my layout in code.
I am trying to follow the steps in https://developer.xamarin.com/guides/xamarin-forms/user-interface/listview/interactivity/#Context_Actions and I want to push a new page when "Edit" is clicked.
I cleaned up my code and removed my feeble attempts to make things work.
So this is my custom list cell:
public class PickerListCell : TextCell
{
public PickerListCell ()
{
var moreAction = new MenuItem { Text = App.Translate ("Edit") };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
var option = (PickerListPage.OptionListItem)mi.CommandParameter;
var recId = new Guid (option.Value);
// This is where I want to call a method declared in my page to be able to push a page to the Navigation stack
};
ContextActions.Add (moreAction);
}
}
And here is my model:
public class OptionListItem
{
public string Caption { get; set; }
public string Value { get; set; }
}
And this is the page:
public class PickerPage : ContentPage
{
ListView listView { get; set; }
public PickerPage (OptionListItem [] items)
{
listView = new ListView () ;
Content = new StackLayout {
Children = { listView }
};
var cell = new DataTemplate (typeof (PickerListCell));
cell.SetBinding (PickerListCell.TextProperty, "Caption");
cell.SetBinding (PickerListCell.CommandParameterProperty, "Value");
listView.ItemTemplate = cell;
listView.ItemsSource = items;
}
// This is the method I want to activate when the context action is called
void OnEditAction (object sender, EventArgs e)
{
var cell = (sender as Xamarin.Forms.MenuItem).BindingContext as PickerListCell;
await Navigation.PushAsync (new RecordEditPage (recId), true);
}
}
As you can see by my comments in the code, I have indicated where I believe things are missing.
Please assist guys!
Thanks!
Probably is too late for you, but can help others. The way i've found to do this is passing the instance of page on creation the ViewCell.
public class PickerListCell : TextCell
{
public PickerListCell (PickerPage myPage)
{
var moreAction = new MenuItem { Text = App.Translate ("Edit") };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
var option = (PickerListPage.OptionListItem)mi.CommandParameter;
var recId = new Guid (option.Value);
myPage.OnEditAction();
};
ContextActions.Add (moreAction);
}
}
So, in your page:
public class PickerPage : ContentPage
{
ListView listView { get; set; }
public PickerPage (OptionListItem [] items)
{
listView = new ListView () ;
Content = new StackLayout {
Children = { listView }
};
var cell = new DataTemplate(() => {return new PickerListCell(this); });
cell.SetBinding (PickerListCell.TextProperty, "Caption");
cell.SetBinding (PickerListCell.CommandParameterProperty, "Value");
listView.ItemTemplate = cell;
listView.ItemsSource = items;
}
void OnEditAction (object sender, EventArgs e)
{
var cell = (sender as Xamarin.Forms.MenuItem).BindingContext as PickerListCell;
await Navigation.PushAsync (new RecordEditPage (recId), true);
}
}
Ok, so with the help of some posts, specifically this one https://forums.xamarin.com/discussion/27881/best-practive-mvvm-navigation-when-command-is-not-available, I came to the following solution, though I'm not perfectly satisfied with the way it looks.
My custom cell now announces when a command is being executed using MessagingCenter:
public class PickerListCell : TextCell
{
public PickerListCell ()
{
var moreAction = new MenuItem { Text = App.Translate ("Edit") };
moreAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
moreAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
var option = (PickerListPage.OptionListItem)mi.CommandParameter;
var recId = new Guid (option.Value);
// HERE I send a request to open a new page. This looks a
// bit crappy with a magic string. It will be replaced with a constant or enum
MessagingCenter.Send<OptionListItem, Guid> (this, "PushPage", recId);
};
ContextActions.Add (moreAction);
}
}
And in my PickerPage constructor I added this subscription to the Messaging service:
MessagingCenter.Subscribe<OptionListItem, Guid> (this, "PushPage", (sender, recId) => {
Navigation.PushAsync (new RecordEditPage (recId), true);
});
All this works just find, but I'm not sure if this is the way it was intended to. I feel like the binding should be able to solve this without the Messaging Service, but I can't find out how to bind to a method on the page, only to a model, and I don't want to pollute my model with methods that have dependencies on XF.

DataGridView - Use DataPropertyName to show child element property

Lets image that I have the following classes
public class Master
{
public string MasterName = "Something";
public List<Detail> details = new List<Detail>();
}
public class Detail
{
public string Foo = "Test";
}
And then I want to show the collection of Details objects in a DataGridView, using the code below
DataGridViewTextBoxColumn column = new DataGridViewTextBoxColumn();
column.DataPropertyName = "Details.Foo";
column.HeaderText = "Foo header";
dgv.Columns.Add(column);
The column is shown in the grid, but without value
If you need to be more generic (i.e. using DataPropertyName = "MyProp1.MyProp2.MyProp3") you can use this
private void Grid_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
DataGridViewColumn column = Grid.Columns[e.ColumnIndex];
if (column.DataPropertyName.Contains("."))
{
object data = Grid.Rows[e.RowIndex].DataBoundItem;
string[] properties = column.DataPropertyName.Split('.');
for (int i = 0; i < properties.Length && data != null; i++)
data = data.GetType().GetProperty(properties[i]).GetValue(data);
Grid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = data;
}
}
You can override ToString method in the entity child for example:
public class FormulariosENT {
#region PROPERTIES
public int IdFromulario { get; set; }
public string DescripcionFormulario { get; set; }
#endregion
#region PUBLIC METHODS
public override string ToString() {
return DescripcionFormulario;
}
And later bind the entity child name.
In case you want to use many child elements like this:
class MyClass
{
public int Id;
public MyOtherClass OtherClass;
}
class MyOtherClass
{
public string Name;
public int Number;
}
How about:
1st solution
Set value for each cell in some event (mabye another one is better), manually, after setting datasource, for example:
private void dgv_CellFormatting( object sender, DataGridViewCellFormattingEventArgs e )
{
MyClass data = dgv.Rows[ e.RowIndex ].DataBoundItem as MyClass;
dgv.Rows[ e.RowIndex ].Cells[ "colName" ].Value = data.OtherClass.Name;
dgv.Rows[ e.RowIndex ].Cells[ "colNumber" ].Value = data.OtherClass.Number;
}
2nd solution
What about creating proper DataTable from the data and then just bind it?
I'd be thankful for any opinion ;-)
Just do this:
Mask the property you want to get a childvalue from with [Browsable(false)] so it wont show up in the datagrid.
Then create a NEW property in your class that holds the child object which has only a "get" method showing the childproperty value:
For example:
[Browsable(false)] //Because we use the CreatorUsernameProperty to do this.
public virtual User Creator { get; set; }
[DisplayName("Creator")] //shows like this in the grid
public string CreatorUsername => Creator?.Username;
where is your datasoure? you must lead to source. that it will find it.
you can do this
source :
:
List<Detail> list = new List<Detail>();
for (int i = 0; i < 10; i++)
{
Detail d = new Detail();
d.Foo = "test";
list.Add(d);
}
this.dgv.DataSource = list;
this.dgv.Columns[0].Visible = false;
DataGridViewTextBoxColumn dgvc = new DataGridViewTextBoxColumn();
dgvc.HeaderText = "列标题";
dgvc.DataPropertyName = "foo";
this.dgv.Columns.Add(dgvc);
:
public class Detail
{
private string foo;
public string Foo
{
get { return foo; }
set { foo = value; }
}
}
bubi's answer is great. I added a small tweak that lets the approach work if you're using BindingListView.
Edit: this approach disables sorting on columns located via subproperty. Not sure how to fix this at the moment.
if (column.DataPropertyName.Contains("."))
{
object data = dgv.Rows[e.RowIndex].DataBoundItem;
if (data is ICustomTypeDescriptor ictd) // support BindingListView
data = ictd.GetPropertyOwner(null);
string[] properties = column.DataPropertyName.Split('.');
for (int i = 0; i < properties.Length && data != null; i++)
data = data.GetType().GetProperty(properties[i])?.GetValue(data);
e.Value = data;
}

C# WPF Binding a text file to datagrid

How can I bind a text file to a datagrid with C# WPF? The idea is to have a row in the text file to show as a row in datagrid.
I don't think you can bind text directly to a datagrid
What you can do however is bind an objet to a datagrid
create an objet representing your text file.
-- content --
text1, param1, param2
text2, param1, param2
class OneLine{
string text {get;set;}
string param { get;set; }
...
}
You can then bind those objects to the datagrid with a BindingList, which is mostly a List. The magic lies in the Properties of the object. The BindingList will try to get each property of the object and display them in the grid.
BindingList<OneLine> myList = new BindingList<OneLine>();
myList.Add(oneObject);
DataGrid myGrid = new DataGrid();
myGrid.DataSource = myList;
In my project I use the following approach
Create class that represent row in text file for example
public class cls_syslog_record
{
public DateTime? f1 {get;set;}
public string f2 {get;set;}
public string f3 {get;set;}
public string f4 {get;set;}
}
Create IEnumerable that used as source for DataGrid
public IEnumerable<cls_syslog_record> get_line_seq_text()
{
cls_mvs_syslog_parser parser = new cls_mvs_syslog_parser();
foreach (string record_line in File.ReadLines(this.filename))
{
cls_syslog_record text_record = parser.parse_syslog_text(record_line);
if (text_record == null)
{
continue;
}
yield return text_record;
}
}
set my IEnumerable object as source
static private DataGrid make_text_viewer(string p_filename)
{
logger.Debug("start");
DataGrid table_viewer;
cls_file_line_seq fl_seq = new cls_file_line_seq(p_filename);
table_viewer = new DataGrid();
table_viewer.CanUserAddRows = false;
table_viewer.CanUserDeleteRows = false;
table_viewer.Columns.Add(create_column("Date Time", "timestamp"));
table_viewer.Columns.Add(create_column("LPAR Name", "lpar_name"));
table_viewer.Columns.Add(create_column("JOB ID", "job_id"));
table_viewer.Columns.Add(create_column("Message", "message"));
table_viewer.HeadersVisibility = DataGridHeadersVisibility.All;
table_viewer.ItemsSource = fl_seq.get_line_seq_text();
return table_viewer;
}
Then setup binding
static private DataGridColumn create_column(string header, string p_property_name)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Header = header;
column.Binding = new Binding(p_property_name);
return column;
}

Categories

Resources