dm k
dm k

Reputation: 131

Binding List of Items in WPF

I try to realize MVVM. TextBox text in View is Binded to property itemName in Model.

On view is DataGrid -> Binded to ViewModel.Rows property

In ViewModel on itemName on change event run async request to remote service for products, which is goes to model SugestProducts property. SugestProducts property is source for ListView items.

If products more than 0 listview open. ListView SelectedItem is Binded to model product property.

I need on product selection in list view fill itemName property from Product.name property without request to remote service. Other work good.

My model is:

public class RowDocumentSaleWraper : INotifyPropertyChanged
{
    private ObservableCollection<Product> _sugestProducts;
    public ObservableCollection<Product> SugestProducts 
    { 
        get
        {
            return _sugestProducts;
        }
        set
        {
            _sugestProducts = value;
            NotifyPropertyChanged("SugestProducts");
        }
    }

        public Product product {get; set;}
         _itemName
        public override string itemName
        {
            get
            {
                return itemName;
            }
            set
            {
                itemName = value;
                NotifyPropertyChanged("itemName");
            }
        }  
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
}

Product:

public class Product
{
    public string name{get; set;}
}

My ViewModel Is:

public class OrderViewModel : DependencyObject
{
       public ObservableCollection<RowDocumentSaleWraper> Rows { get; set; }

    public OrderViewModel()
    {
        addNewRow();
    }
        internal void addNewRow()
        {
            RowDocumentSaleWraper row = new RowDocumentSaleWraper(Order);
            row.PropertyChanged += row_PropertyChanged;
            Rows.Add(row);
        }
    void row_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        RowDocumentSaleWraper row = sender as RowDocumentSaleWraper;

        if (row != null && e.PropertyName == "itemName" && !String.IsNullOrEmpty(row.itemName))
        {
            //get products from remote service -> source for 
            requestProducts(row.itemName, row);
        }
    }
    private async void requestProducts(string searchString, RowDocumentSaleWraper row)
    {
        if (!String.IsNullOrEmpty(searchString))
        {
            var products = await requestProductsAsync(searchString);

            row.SugestProducts = listToObservable(products);
        }

    }
}

My Xaml:

<DataGrid Grid.Row="1" Name="mainDataGrid" ItemsSource="{Binding Rows , UpdateSourceTrigger=PropertyChanged}" AutoGenerateColumns="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Product">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <StackPanel Orientation="Vertical">
                                <TextBox PreviewKeyDown="TextBox_PreviewKeyDown" KeyDown="TextBox_KeyDown" Text="{Binding itemName, UpdateSourceTrigger=PropertyChanged}" MinWidth="200"/>
                                <ListView ItemsSource="{Binding SugestProducts, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  
                                          KeyDown="ListView_KeyDown" SelectedItem ="{Binding product, UpdateSourceTrigger=PropertyChanged}">
                                    <ListView.View>
                                        <GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
                                            <GridViewColumn  DisplayMemberBinding="{Binding code}"/>
                                            <GridViewColumn  DisplayMemberBinding="{Binding name}" />
                                        </GridView>
                                    </ListView.View>
                                </ListView>
                            </StackPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

Upvotes: 0

Views: 3285

Answers (1)

user6996876
user6996876

Reputation:

Based on the above comments, you should notify the ViewModel from the setter on itemName

    public override string itemName
    {
        get
        {
            return itemName;
        }
        set
        {
            itemName = value;
            NotifyPropertyChanged("itemName");
            NotifyChange(itemName); 
        }
    } 

Then you'll define the event to retrieve the data

private async void NotifyChange(string name)
{
    if (!String.IsNullOrEmpty(searchString))
    {
        var products = await requestProductsAsync(searchString);

        SugestProducts = listToObservable(products);
    }
}

Upvotes: 1

Related Questions