简体   繁体   中英

mvvm:filter wpf listview values from a textbox

I am new to MVVM .I have a requirement .I have one textbox and one listview .When the user enter text on textbox the listview got populated with data by filtering through the text. And the user can Select one item from the listview then the textbox get the Selectedvalue and listview get invisible(after an item is selected).I can do this in wpf normal code,But I dont know how to do this in MVVM pattern. Here is my View in normal wpf:

<TextBox  Name="txtbxProductName"
          TextChanged="txtbxProductName_TextChanged"
          KeyUp="txtbxProductName_KeyUp"
          />

<ListView Name="lstvwProduct"
          Visibility="Collapsed"
          MouseLeftButtonUp="lstvwProduct_MouseLeftButtonUp"
          KeyDown="lstvwProduct_KeyDown">
    <ListView.View>
      <GridView>
        <GridViewColumn DisplayMemberBinding="{Binding Path=Product_Name}"
                        Header="Product Name"
                        Width="240" />
         <GridViewColumn DisplayMemberBinding="{Binding Path=Product_Code}"
                         Header="Product Code"
                         Width="80" />
        </GridView>
       </ListView.View>
     </ListView>

Here is my Code behind events:

private void txtbxProductName_TextChanged(object sender, TextChangedEventArgs e)
{
    if (txtbxProductName.Text.Trim() != "")
    {
        string Query = "select PM.Record_Id ,PM.Product_Code,PM.Product_Name,PTM.Product_Type from dbo.Tbl_Product_Master PM  where PM.Is_Del='false' and PM.Product_Name like '%" + txtbxProductName.Text + "%' order by PM.Product_Name ";
        DataSet ds = new DataSet();
        ds = ObjCommon.GetObject.ExecuteQuery_Select(Connection.ConnectionString, Query);
        if (ds.Tables[0].Rows.Count != 0)
        {
            lstvwProduct.Visibility = Visibility.Visible;
            lstvwProduct.ItemsSource = ds.Tables[0].DefaultView;
        }
        else
        {
            lstvwProduct.Visibility = Visibility.Collapsed;
        }
    }
    else
    {
        lstvwProduct.Visibility = Visibility.Collapsed;
    }
}

private void txtbxProductName_KeyUp(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Escape)
    {
        txtbxProductName.Text = "";
        lstvwProduct.Visibility = Visibility.Collapsed;
    }
    else if (e.Key == Key.Down)
    {
        lstvwProduct.Focus();
        lstvwProduct.SelectedIndex = 0;
    }
}

private void lstvwProduct_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    if (lstvwProduct.SelectedIndex != -1)
    {
        DataRowView drv = (DataRowView)lstvwProduct.SelectedItem;
        txtbxProductName.Text = drv.Row["Product_Name"].ToString();
        lstvwProduct.Visibility = Visibility.Collapsed;
    }
}

private void lstvwProduct_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        if (lstvwProduct.SelectedItem != null)
        {
            DataRowView drv = (DataRowView)lstvwProduct.SelectedItem;
            txtbxProductName.Text = drv.Row["Product_Name"].ToString();
            lstvwProduct.Visibility = Visibility.Collapsed;
        }
    }
    else if (e.Key == Key.Escape)
    {
        lstvwProduct.Visibility = Visibility.Collapsed;
        txtbxProductName.Focus();
    }
}

How to Accomplish this in MVVM Here is my View:

<TextBox  Name="txtbxProductName"
          Width="119"
          Text="{Binding Path=ProductName,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"
          />

 <ListView ItemsSource="{Binding Path=ProductRecords}"
           SelectedItem="{Binding Path=SelectedProduct,Mode=TwoWay}"
           IsSynchronizedWithCurrentItem="True"
           Name="lstvwProduct"
            >
      <ListView.View>
        <GridView>
          <GridViewColumn DisplayMemberBinding="{Binding Path=ProductName}"
                          Header="Product Name"
                          Width="100" />
          <GridViewColumn DisplayMemberBinding="{Binding Path=ProductCode}"
                          Header="Product Code"
                           Width="100" />
         </GridView>
      </ListView.View>
 </ListView>

Here is my ViewModel Properties:

private string _productName;
public string ProductName
{
    get { return _productName; }
    set
    {
        _productName = value;
        RaisePropertyChanged("ProductName");
    }
}
private List<Tbl_Product_Master> _ProductRecords;
public List<Tbl_Product_Master> ProductRecords
{
    get { return _ProductRecords; }
    set
    {
        _ProductRecords = value;
        RaisePropertyChanged("ProductRecords");
    }
}
 private Tbl_Product_Master _selectedProduct;
 public Tbl_Product_Master SelectedProduct
{
    get { return _selectedProduct; }
    set
    {
        _selectedProduct = value;
        RaisePropertyChanged("SelectedProduct");
    }
}

How to do this in MVVM?

Add an additional property to your viewmodel to show/hide the ListView:

private bool showProductList;
public bool ShowProductList
{
   get { return showProductList; }
   set 
   { 
       showProductList = value;
       RaisePropertyChanged("ShowProductList");
   }
}

Wire up a PropertyChanged Handler in your Viewmodel and set your properties as required:

public MyViewModel()
{
   PropertyChanged += MyViewModel_PropertyChanged;
}

private bool handleSelectedProductChanges = true;

void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
   if(e.PropertyName == "ProductName")
   {
      handleSelectedProductChanges = false;

      // update ProductRecords

      handleSelectedProductChanges = true;
   }
   else if(e.PropertyName == "SelectedProduct")
   {
      if (handleSelectedProductChanges && SelectedProduct != null)
      {
          ProductName = SelectedProduct.Name;
          ShowProductList = false;
      }
    }
}

To bind the Visibility of your ListView you need a bool-to-visibility converter.

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