XML :
<?xml version="1.0" encoding="utf-8"?>
<servers>
<server>s2
<database>db1</database>
<database>db2</database>
</server>
<server>s3
<database>db3</database>
<database>db4</database>
</server>
</servers>
I want to get database based on server name & return as a list of string type.
view :
This function will take server name as a parameter from first combo box and based on the will filter database and populate second combobox
public List<string> GetDatabases(string serv)
{
var item = from items in xdoc.Descendants("database")
where (string)items.Element("server") == serv
select items.Elements("database").ToList();
foreach (var items in item)
{
lstDBName.Add(items.ToString());
}
return lstDBName;
}
The XML you posted is not valid. If you test it with an XML validator you will see it gives this error:
Errors in the XML document:
1: 1 Content is not allowed in prolog.
You can easily fix it by adding an attribute to store server name like this:
<?xml version="1.0" encoding="utf-8"?>
<servers>
<server name="s2">
<database>db1</database>
<database>db2</database>
</server>
<server name="s3">
<database>db3</database>
<database>db4</database>
</server>
</servers>
And you can modify (and simplify a bit) your code like this:
public List<string> GetDatabases(string serv)
{
XDocument xdoc = XDocument.Load("XMLFile1.xml");
var lstDBName = (from items in xdoc.Descendants("server")
where items.Attribute("name").Value == serv
from item in items.Elements("database")
select item.Value)
.ToList();
return lstDBName;
}
I read the XML inside the method from a file called XMLFile1.xml, you can change that bit with however you're reading the XML.
This code sample would return a list of two strings with values "db1" and "db2" as expected
As I can understand, you need some mechanism which on selection in first combo will update the second combo with first combo related data (based on your question name:
i have two combo boxes and xml file, i want to populate server name in combo box 1 from xml and based on server name populate second combo box
).
Here is a solution which is based on two observable collections an its update mechanisms.
1. Xaml code:
<Window x:Class="SimpleDataGrid.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:simpleDataGrid="clr-namespace:SimpleDataGrid"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<simpleDataGrid:GridViewModel/>
</Window.DataContext>
<Grid >
<DataGrid x:Name="SelectDataGrid" ItemsSource="{Binding Persons}" HorizontalAlignment="Left" VerticalAlignment="Top" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn x:Name="dgCheckBox" Header="Select" Width="45" Binding="{Binding IsChecked}"/>
<DataGridTextColumn Header="FIRST NAME" Width="125" Binding="{Binding FNAME}"/>
<DataGridTextColumn Header="LAST NAME" Width="125" Binding="{Binding LNAME}"/>
<DataGridComboBoxColumn Header="Servers"
DisplayMemberPath="ServerName" SelectedValueBinding="{Binding SelectedServer, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=DataContext.Servers}"/>
<Setter Property="IsReadOnly" Value="True"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=DataContext.Servers}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridComboBoxColumn Header="Dbs"
DisplayMemberPath="DbName"
SelectedValueBinding="{Binding SelectedDb, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=DataContext.Dbs}"/>
<Setter Property="IsReadOnly" Value="True"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}, Path=DataContext.Dbs}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
</DataGrid.Columns>
</DataGrid>
</Grid></Window>
2. Main Model Code which gives the solution.The UpdateDbCollection method can call your GetDatabases method, query server related data bases, put that data to the 'newDbs' list and update the second combo observable collections with new data in way when it add a new data and remode an old data.
public class Person : BaseObservableObject
{
private string _lName;
private string _fName;
private bool _checked;
private object _selectedServer;
private DbDetails _selectedDb;
public Person()
{
Dbs = new ObservableCollection<DbDetails>();
Servers = new ObservableCollection<ServerDetails>(new List<ServerDetails>
{
new ServerDetails
{
ServerName = "A",
DbDetailses = new List<DbDetails>
{
new DbDetails{DbName = "AA"},
new DbDetails{DbName = "AB"},
new DbDetails{DbName = "AC"},
}
},
new ServerDetails
{
ServerName = "B",
DbDetailses = new List<DbDetails>
{
new DbDetails{DbName = "BA"},
new DbDetails{DbName = "BB"},
new DbDetails{DbName = "BC"},
}
},
new ServerDetails
{
ServerName = "C",
DbDetailses = new List<DbDetails>
{
new DbDetails{DbName = "CA"},
new DbDetails{DbName = "CB"},
}
}
});
}
public DbDetails SelectedDb
{
get { return _selectedDb; }
set
{
_selectedDb = value;
OnPropertyChanged();
}
}
public object SelectedServer
{
get { return _selectedServer; }
set
{
_selectedServer = value;
OnPropertyChanged();
UpdateDbCollection(SelectedServer as ServerDetails);
}
}
private void UpdateDbCollection(ServerDetails serverDetails)
{
//here you can get your db details by selected server
var newDbs = serverDetails.DbDetailses;
newDbs.ForEach(details => Dbs.Add(details));
var valuesToClear =
Dbs.Where(
existingDbDetails => newDbs.FirstOrDefault(dbDetails => existingDbDetails == dbDetails) == null).ToList();
valuesToClear.ForEach(details => Dbs.Remove(details));
}
public ObservableCollection<ServerDetails> Servers { get; set; }
public ObservableCollection<DbDetails> Dbs { get; set; }
public bool IsChecked
{
get { return _checked; }
set
{
_checked = value;
OnPropertyChanged();
}
}
public string LNAME
{
get { return _lName; }
set
{
_lName = value;
OnPropertyChanged();
}
}
public string FNAME
{
get { return _fName; }
set
{
_fName = value;
OnPropertyChanged();
}
}
}
3. Models:
public class ServerDetails:BaseObservableObject
{
private string _serverName;
public string ServerName
{
get { return _serverName; }
set
{
_serverName = value;
OnPropertyChanged();
}
}
public List<DbDetails> DbDetailses { get; set; }
}
public class DbDetails:BaseObservableObject
{
private string _dbName;
public string DbName
{
get { return _dbName; }
set
{
_dbName = value;
OnPropertyChanged();
}
}
}
View model code:
public class GridViewModel:BaseObservableObject
{
public GridViewModel()
{
var l = new List<Person>
{
new Person {FNAME = "John", LNAME = "W"},
new Person {FNAME = "George", LNAME = "R"},
new Person {FNAME = "Jimmy", LNAME = "B"},
new Person {FNAME = "Marry", LNAME = "B"},
new Person {FNAME = "Ayalot", LNAME = "A"},
};
Persons = new ObservableCollection<Person>(l);
}
public ObservableCollection<Person> Persons { get; set; }
}
BaseObservableObject is a simple implementation of INotifyPropertyChanged.
I hope it will help you.
Thanks an regards,