How to pass value from DB to Listview/Grid View via binding? - c#

I need to pass a value from a database to Listview via a binding. I managed to make static data by simply adding values to the List and linking them to the desired columns. But I don't understand how to make it so that I could display values from my database (I work through the connection string and MySQL).
What the markup looks like
<ListView
Name="LVBuild">
<ListView.View>
<GridView>
<GridViewColumn
DisplayMemberBinding="{Binding ID}"
Header="ID" />
<GridViewColumn
DisplayMemberBinding="{Binding Title}"
Header="Title" />
<GridViewColumn
DisplayMemberBinding="{Binding Description}"
Header="Description" />
<GridViewColumn
DisplayMemberBinding="{Binding BuildData}"
Header="BuildDate">
<GridViewColumn.CellTemplate>
My model
public class BuildModel
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string BuildData { get; set; }
public int Architect { get; set; }
public int Location { get; set; }
public int Teg { get; set; }
}
public class BuildManager
{
public static List<BuildModel> GetBuilds()
{
List<BuildModel> items = new List<BuildModel>();
items.Add(new BuildModel() {ID = 1, Title = "Test1", Description = "Desc1", BuildData = "12.12.2022", Architect = 1, Location = 1, Teg = 1});
items.Add(new BuildModel() {ID = 2, Title = "Test2", Description = "Desc2"});
items.Add(new BuildModel() {ID = 3, Title = "Test3"});
items.Add(new BuildModel() {ID = 4, Title = "Test4"});
return items;
}
}
How do I pass values from a model
public partial class BuildPageAdmin : Page
{
private List<BuildModel> Builds;
public BuildPageAdmin()
{
InitializeComponent();
LVBuild.ItemsSource = BuildManager.GetBuilds();
}
}

Simply use data binding: create a public property to hold the source collection and update it with data from your database. Data binding overview (WPF .NET)
If your collection is a ObservableCollection you can update it dynamically:
<Page>
<ListView ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=Page}, Path=Builds}">
</ListView>
</Page>
public partial class BuildPageAdmin : Page
{
// Create a binding source for the ListView
public ObservableCollection<BuildModel> Builds { get; }
public BuildPageAdmin()
{
InitializeComponent();
this.Builds = new ObservableCollection<BuildModel>();
this.Loaded += OnPageLoaded;
}
private void OnPageLoaded(object sender, RoutedEventArgs e)
=> UpdateBuildModels();
// Dynamically update the source collection at any time
private void UpdateBuildModels()
{
this.Builds.Clear();
// Get data from database
IEnumerable<BuldModel> newBuildModels = BuildManager.GetBuilds();
// Update source collection with new data from the database
foreach (BuildModel buildModel in newBuildModels)
{
this.Builds.Add(bulidModel);
}
}
}

Related

How can I set a selection in a DataGridComboBoxColumn?

How can I set a DataGridComboBoxColumn item selection programmatically?
I want to populate my list with data, and the comboboxitem should set the selected item from the list.
But I dont find any way to achieve that.
In this example the selection should be "Forward"
XAML:
<DataGrid ItemsSource="{Binding }" x:Name="dgSFD" AlternatingRowBackground="BlanchedAlmond" SelectionChanged="dgSFD_SelectionChanged" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=sID}" Header="Step ID"/>
<DataGridComboBoxColumn x:Name="cbServo" Header="Servo" SelectedItemBinding="{Binding Servo, Mode =TwoWay}" SelectedValuePath="sFunctionName ,Mode=TwoWay" DisplayMemberPath="sFunctionName"/>
</DataGrid>
Class
public class Step
{
public string sID { get; set; }
public Servo serServo { get; set; }
}
public class Servo
{
public string sFunction { get; set; }
public string sServo { get; set; }
}
C#
public static List<Step> listStep { get; set; }
public static List<Servo> listServo { get; set; }
public MainWindow()
{
InitializeComponent();
}
public void loadList()
{
dgSFD.ItemsSource = listStep;
cbServo.ItemsSource = listServo;
}
public void testfill()
{
Servo newServo = new Servo();
newServo.sFunctionName = "Forward";
newServo.sServo = "Left";
listServo.Add(newServo);
Step newStep = new Step();
newStep.serServo = newServo;
newStep.sID = "1";
listStep.Add(newStep);
}
Bind the SelectedItemBinding property to the serServo property of the Step object:
<DataGridComboBoxColumn x:Name="cbServo" Header="Servo" SelectedItemBinding="{Binding serServo, Mode=TwoWay}" DisplayMemberPath="sFunction"/>

How to: Fill a DataGrid.DataContext with information from txt files (C#, WPF)

How to: Fill a DataGrid.DataContext with information from txt files (C#, WPF)
I am trying to fill my DataGrid with information I get from some txt files. There is a folder called "CONTACTS" and there are some (5) files in. These files are configurated this way:
Content of John Doe.txt (without list symbols):
John Doe Corp.
Mr.
Doe
John
XAML:
<DataGrid AutoGenerateColumns="False" CanUserResizeRows="False" DockPanel.Dock="Bottom" ItemsSource="{Binding CollectionofDetails}" Name="dataGrid_Content">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding CorporationName}" Header="Firma" />
<DataGridTextColumn Binding="{Binding Prefix}" Header="Anrede" />
<DataGridTextColumn Binding="{Binding FirstName}" Header="Nachname" />
<DataGridTextColumn Binding="{Binding LastName}" Header="Vorname" />
</DataGrid.Columns>
</DataGrid>
C#:
public class Details
{
public string CorporationName { get; set; }
public string Prefix { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public ObservableCollection<Details> _CollectionofDetails = new ObservableCollection<Details>();
public ObservableCollection<Details> CollectionofDetails
{
get { return _CollectionofDetails; }
set { _CollectionofDetails = value; }
}
public void SetItemsToDataContext()
{
foreach (string Datei in Directory.GetFiles(#"C:\Users\schwarz\Desktop\Cusposes_2014-05-20_0827\ISAPO\ISAPO Cusposes\Business Contacts\Contacts", "*.txt"))
{
StreamReader reader = new StreamReader(Datei);
int i = 0;
string line = reader.ReadToEnd().Replace("\n", "");
string[] t = line.Split('\r');
Details d = new Details();
d.CorporationName = t[i];
d.Prefix = t[i + 1];
d.FirstName = t[i + 2];
d.LastName = t[i + 3];
CollectionofDetails.Add(d);
reader.Close();
}
}
Unfortunately, I do have the following problems:
I do not know how to load THE CONTENT of each file (for all files).
I do not know how to fill my DataGrid with this Information.
--> Solution by Dhaval Patel (see below).
You can use the below mentioned code
Your Xaml Code looks like
<DataGrid AutoGenerateColumns="False" CanUserResizeRows="False" DockPanel.Dock="Bottom" ItemsSource="{Binding CollectionofDetails}" Name="dataGrid_Content">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding CorporationName}" Header="Firma" />
<DataGridTextColumn Binding="{Binding Prefix}" Header="Anrede" />
<DataGridTextColumn Binding="{Binding FirstName}" Header="Nachname" />
<DataGridTextColumn Binding="{Binding LastName}" Header="Vorname" />
</DataGrid.Columns>
</DataGrid>
<Button Command="{Binding MyCommand}" Width="100" Margin="346,230,346,-189">RunMyCommand</Button>
Your ViewModel code look like
private ObservableCollection<Details> _CollectionofDetails=new ObservableCollection<Details>();
public ObservableCollection<Details> CollectionofDetails
{
get { return _CollectionofDetails; }
set { _CollectionofDetails = value; RaisePropertyChanged("CollectionofDetails"); }
}
private RelayCommand _MyCommand;
public RelayCommand MyCommand
{
get { return _MyCommand??(_MyCommand=new RelayCommand(Methodcall)); }
set { _MyCommand = value; }
}
void Methodcall()
{
foreach (string Datei in Directory.GetFiles(#"C:\textfile", "*.txt"))
{
StreamReader reader = new StreamReader(Datei);
int i=0;
string line = reader.ReadToEnd().Replace("\n","");
string[] t = line.Split('\r');
Details d = new Details();
d.CorporationName = t[i];
d.Prefix = t[i + 1];
d.FirstName = t[i + 2];
d.LastName = t[i + 3];
CollectionofDetails.Add(d);
reader.Close();
}
}
public class Details
{
public string CorporationName { get; set; }
public string Prefix { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
output should look like
This is a problem that you have to break into pieces. I would recommend that you define a class suitable for your data, like
public class Person {
public string FullName {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
public string Title {get; set;}
}
and in your viewmodel class you have a variable PersonList of type List<Person>.
Then your have to write a method, something like
private void PopulatePersonData(){
// Here you put all the logic reading the .txt files creating a person for each file
// and adding the person to the PersonList.
}
which you then call in the constructor of the viewmodel.
Finally you bind the ItemsSource of your DataGrid to the PersonList. That should do it.
Maybe you should really read what is in your txt files.
By using for example a Reader :
private void SetItemsToDataContext()
{
foreach (String Datei in Directory.GetFiles(#"C:\Contacts", "*.txt"))
{
String[] linesRead = File.ReadAllLines(Datei);
if (linesRead.Length != 4)
{
continue;
}
Contact contactRead = new Contact();
contactRead.Company = linesRead[0];
contactRead.Gender = linesRead[1];
contactRead.Name = linesRead[2];
contactRead.FirstName = linesRead[3];
dataGrid_Content.Items.Add(contactRead);
}
}
public class Contact
{
public String Company { get; set; }
public String Gender { get; set; }
public String Name { get; set; }
public String FirstName { get; set; }
}

ObservableCollection with INotifyPropertyChanged into DatagridComboboxColumn Binding

My little project looks now quite different. Now I have ObservableCollection PackagesList with data which I want to bind with whole DataGrid (via Binding Path) and ObservableCollection DestinationItememsSource where I store cases for DataGridComboboxColumn (as ItemsSourceBinding). SelectedItem property in DatagridComboboxColumn is one value from PackageInfo (and it is one of DestinationNames cases ofc). Binding on DatagridTextBoxColumns is ok.
XAML:
<Window x:Class="test01.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="400" Loaded="Window_Loaded">
<Grid>
<Border x:Name="mainBorder" Margin="20">
<DataGrid x:Name="mainDataGrid" x:Uid="mainDataGrid" AutoGenerateColumns="False"
AlternationCount="2" SelectionMode="Single" HorizontalAlignment="Stretch">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Path=id}"
Header="ID" Width="Auto" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Path=name}"
Header="Name" Width="Auto" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Path=quantity}"
Header="Quantity" Width="Auto" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Path=price}"
Header="Price" Width="Auto" IsReadOnly="True"/>
<DataGridComboBoxColumn ItemsSource="{Binding DestinationItemsSource}"
SelectedItemBinding="{Binding Path=destination, UpdateSourceTrigger=PropertyChanged}"
Header="Destination" Width="Auto"/>
</DataGrid.Columns>
</DataGrid>
</Border>
</Grid>
</Window>
C#:
public class PackageInfo
{
public int id { get; set; }
public string name { get; set; }
public int quantity { get; set; }
public double price { get; set; }
public string destination { get; set; }
}
public class DestinationNames : INotifyPropertyChanged
{
public string name { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public DestinationNames(string value)
{
this.name = value;
}
public string DestinationName
{
get { return name; }
set
{
name = value;
OnPropertyChanged("DestinationName");
}
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
public partial class MainWindow : Window
{
public ObservableCollection<DestinationNames> DestinationItememsSource { get; set; }
public ObservableCollection<PackageInfo> PackagesList { get; set; }
public MainWindow()
{
InitializeComponent();
}
public void Window_Loaded(object sender, RoutedEventArgs e)
{
LoadPackages();
}
public void LoadPackages()
{
DestinationItememsSource = new ObservableCollection<DestinationNames>();
DestinationItememsSource.Add(new DestinationNames("London"));
DestinationItememsSource.Add(new DestinationNames("Plymouth"));
DestinationItememsSource.Add(new DestinationNames("Birmingham"));
DestinationItememsSource.Add(new DestinationNames("Cambridge"));
PackagesList = new ObservableCollection<PackageInfo>();
PackagesList.Add(new PackageInfo { id = 1, name = "Potato", quantity = 3, price = 2.2, destination = "London" });
PackagesList.Add(new PackageInfo { id = 2, name = "Tomato", quantity = 5, price = 3.8, destination = "Plymouth" });
PackagesList.Add(new PackageInfo { id = 3, name = "Carrot", quantity = 1, price = 5.1, destination = "London" });
PackagesList.Add(new PackageInfo { id = 4, name = "Pea", quantity = 6, price = 1.8, destination = "Plymouth" });
PackagesList.Add(new PackageInfo { id = 5, name = "Bean", quantity = 2, price = 1.5, destination = "Birmingham" });
mainDataGrid.ItemsSource = PackagesList;
}
}
How to bind this DatagridComboboxColumn properly? Should I use INotifyCollectionChanged ?? What if I want to all data in datagrid will be automatically synced with ObservableCollection ?? Please help with some example.
Have PackageInfo implement INotifyPropertyChanged.
An ObservableCollection automatically implements INotifyCollectionChanged.
You will need to add List or ObservableCollection Destinations as a property of PackageInfo
NO class DestinationNames
Just a class DestinationName
Your binding to DestinationItememsSource does not work, because it isnt part of the PackageInfo object. You also cant bind to the Windows DataContext via FindAncestor or ElementName-binding because DataGrid-Columns wont be added to the visual tree.
One solution I can think of is using the CollectionViewSource:
<Window.Resources>
<CollectionViewSource Source="{Binding RelativeSource={RelativeSource Self}, Path=DestinationItememsSource}" x:Key="destinations">
<!--here you can also add Group and SortDescriptions-->
</CollectionViewSource>
</Window.Resources>
<DataGridComboBoxColumn ItemsSource="{Binding Source={StaticResource ResourceKey=destinations}}".../>
I cant test it atm, because I'm still downloading VS 2012.^^
Anotherone would be to simply add a List of Destinations to your PackageInfo object (but this would cause a lot of redundancies).

Different values for different comboboxes in Datagrid

Bear with me, as I'm new to WPF.I have a datagrid which contains comboboxes.
<DataGrid x:Name="dgData" AutoGenerateColumns="False" Margin="131,93,13,101" Grid.Column="1" SelectionChanged="dgData_SelectionChanged">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Subject}" Header="Subject" Width="100"/>
<DataGridComboBoxColumn Header="Subject" x:Name="comboboxColumn1"/>
</DataGrid.Columns>
</DataGrid>
And I use the following code to load different itemsources depending on which combobox is clicked on by the user:
private void dgData_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (dgData.SelectedIndex == 0)
{
comboboxColumn1.ItemsSource = resolution;
} else if (dgData.SelectedIndex == 1)
{
comboboxColumn1.ItemsSource = codec;
}
}
How I bind dgData:
List<TicketInfo> ticketsList = new List<TicketInfo>
{
new TicketInfo{ Subject="File", Status="Open"},
new TicketInfo{ Subject="Resolution", Status="Assigned"},
};
dgData.ItemsSource = ticketsList;
public class TicketInfo
{
public string Subject { get; set; }
public string Status { get; set; }
}
Now I also need to retrieve the value of the combobox once the user chooses the value. Is there a more elegant way to load different items in different comboboxes and retrieving the value?
Thanks!
You don't show how you bind dgData.
public class TicketInfo
{
public string Subject { get; set; }
public string Status { get; set; }
public List<string> SubjectSubList { get; set; }
}
Bind the second column to SubjectSubList
When you build List ticketsList just put resolution in the first SubjectSubList and codec in the second.

Update listview from code behind

I have the following code in xaml:
<ListView Name="listView1" IsSynchronizedWithCurrentItem="True" >
<ListView.View>
<GridView>
<GridViewColumn Header="MyList">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Cost, Mode=TwoWay}"></TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
on my code behind I have:
public partial class LogIn : UserControl, INotifyCollectionChanged
{
class Product
{
public string Name { get; set; }
public int Cost { get; set; }
}
ObservableCollection<Product> MyList = new ObservableCollection<Product>()
{
new Product(){ Cost=14},
new Product(){ Cost=15},
new Product(){ Cost=5},
new Product(){ Cost=20}
};
event NotifyCollectionChangedEventHandler INotifyCollectionChanged.CollectionChanged
{
add { throw new NotImplementedException(); }
remove { throw new NotImplementedException(); }
}
// constructor
public LogIn()
{
InitializeComponent();
listView1.DataContext = MyList;
}
private void button5_Click(object sender, RoutedEventArgs e)
{
this.MyList[0].Cost = 123456789;
// !!!!!!!!!!!!!!! I want the listview to update when I press this button
}
The listview does not change when I update on the last method. what do I have to do so that I can update the listview cost values with code behind?
Edit
Thanks to SLaks I made the following changes to my Product class and it worked.
public class Product : INotifyPropertyChanged
{
private int _cost;
public string Name { get; set; }
public int Cost
{
get
{
return _cost;
}
set
{
_cost = value;
OnPropertyChanged("Cost");
}
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
also I added the following line in the constructor of the usercontroll:
listView1.ItemsSource = MyList;
You need to implement INotifyPropertyChanged in the Product class so that WPF knows when your properties change.

Categories

Resources