简体   繁体   中英

Problems displaying items in a listview based off of a ComboBox in WPF C#

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();  
    }
}

}

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}" ... />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM