Reputation: 241
Im coming from a limited background with Windows Forms and making the jump to WPF. Still struggling with databinding.
So I have a WPF application and it is pretty simple. I have an ADO.Net entity model which has all of my database information in it. I am working with one table with a few columns. Basically I have a Combo Box which contains all of the names of the items in the database. This part is working fine. What I have below it is a ListView which will display the other Columns, such as Qty. Right now I want to only load one row into the Listview with one column of data. starting off simple. Once i get this right, I will add the other columns. The problem, I initially had was if I just bound both of the objects (combobox and the list view), the listview would display ALL of the rows in the database. the isSynchronizedWithCurrentItem would just make the listview highlight whatever was selected in the combobox. I want to narrow that down with the selection in the combo box. This was the best I could come up with digging through this site and a couple boos I have, so any information would be helpful!
Coming from WinForms, I used to use table adapters to hold the queries with parameters that I could use to return data, which made it much easier to re-use queries. If there is a way to do this with ADO.net, that would be awesome!
My XAML looks like this
<Window x:Class="InventoryTest.TestPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Information" Height="362" Width="614"
Loaded="Window_Loaded">
<Window.Resources>
<DataTemplate x:Key="InventoryTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=InventoryName}" />
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ComboBox x:Name="ingNameCB" Margin="40,16,42,0" VerticalAlignment="Top" Height="23" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding}" ItemTemplate="{StaticResource InventoryTemplate}" ></ComboBox>
<Button x:Name="saveChanges" Content="Save Changes" HorizontalAlignment="Left" Margin="40,0,0,10" VerticalAlignment="Bottom" Width="90" IsEnabled="False" Height="23"/>
<ListView x:Name="ingListLV" Margin="40,44,40,165" IsSynchronizedWithCurrentItem="True" DataContext="{Binding ElementName=ingNameCB, Path=SelectedItem}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Width="100" Header="Qty" DisplayMemberBinding="{Binding Path=Qty}" />
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
My code behind looks like this:
public partial class SupplierInfo : Window
{
private AuroraEntities1 auroraContext = null;
public SupplierInfo()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.auroraContext = new AuroraEntities1();
//Connects the combobox to the database. the datatemplate and databindings display the proper values
ingNameCB.DataContext = this.auroraContext.Inventories;
//Selects the row QTY where InventoryName is equal to the current selection of the combobox
ObjectQuery<Inventory> inventories = auroraContext.Inventories;
string name = ingNameCB.SelectedItem.ToString();
var FillList = from q in inventories
where q.InventoryName == name
select q.Qty.ToString();
//Fills the listview with only the selected qty
ingListLV.ItemsSource = FillList.ToString();
}
}
}
Upvotes: 1
Views: 467
Reputation: 102793
ListView.ItemsSource
should be a collection type. To set ItemsSource
directly then, I think what you want is this:
var FillList = from q in inventories
where q.InventoryName == name
select q;
ingListLV.ItemsSource = FillList.ToList();
However, it sounds like you want the list to update/requery when the user changes a selection, right? There are multiple ways to do this; one way is a data-bound property like "Items" that will get re-queried on change. Normally you'd want to use a view-model for this, but I'll use code-behind for simplicity:
<Window
...
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
Make the Window class implement INotifyPropertyChanged
, and give it SelectedItem
and Items
properties:
public partial class SupplierInfo : Window, INotifyPropertyChanged
{
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
RaisePropertyChanged("InventoryItems");
}
}
private string _selectedItem;
public List<Inventory> InventoryItems
{
get
{
var FillList = from q in inventories
where q.InventoryName == SelectedItem
select q;
return FillList.ToList();
}
}
...
}
Now bind the ComboBox to the SelectedItem
property:
<ComboBox x:Name="ingNameCB" SelectedItem="{Binding SelectedItem,Mode=TwoWay}" ... />
Finally, bind the ListView
to the InventoryItems
property (note that this will get refreshed whenever the user selects a new item in the combo box, triggering a call to the getter of InventoryItems
, thus re-querying the data source):
<ListView ItemsSource="{Binding InventoryItems}" ... />
Upvotes: 1