简体   繁体   中英

Bind button click to set Icollection view source

When my aapp launched i read a pricing file method attached to the soource using viewm-model approach then display it to the datagrid.

I'm trying to read the pricing file when i click on a button then attach the method to the view source.

I tried to set the view source on button click but nothing is displayed in the datagrid? thanks for your help.

case "ReadPricing": //to read local pricing file
cvs.Source = GetProductsPriceListXML(); // method to read the xml file 
cvs.View.Filter = Filter;
View = cvs.View;
return;

Button:

  <Button x:Name="breadxml"  HorizontalAlignment="Center" Margin="62,10" Width="76"  Command="{Binding MyCommand}" CommandParameter="ReadPricing" Height="43" >
                <TextBlock Text="Read Pricing File" TextWrapping="Wrap" TextAlignment="Center"/>
            </Button>

Datagrid:

        <DataGrid VerticalAlignment="Top" HorizontalAlignment="Left" 
          SelectedItem="{Binding SelectedProduct}"
          ItemsSource="{Binding View}" AutoGenerateColumns="False" 
          CanUserAddRows="False" ScrollViewer.VerticalScrollBarVisibility="Visible" 
          Margin="0,2,0,0"   
          Height="{Binding RelativeSource={RelativeSource AncestorType={x:Type DockPanel}}, Path=ActualHeight}"  >
            <DataGrid.Columns>
                <DataGridTextColumn Header="MianProduct" Binding="{Binding Mainproduct}" Width="*" IsReadOnly="True"/>
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*" IsReadOnly="True"/>
                <DataGridTextColumn Header="Price" Binding="{Binding Price}" Width="*" />
                <!--<DataGridTextColumn Header="Visible" Binding="{Binding Visible}" Width="*" />-->
                <DataGridTemplateColumn Header="Visible"  Width="100" >
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding Visible, UpdateSourceTrigger=PropertyChanged}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="NameIcon" Binding="{Binding NameIcon}" Width="*" />
            </DataGrid.Columns>
        </DataGrid>

Datacontext/convertor:

 <Window.DataContext>
        <local:ProductPriceViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <local:MediaConverter x:Key="mconv" />
    </Window.Resources>

Class-ViewModel:

class ProductPriceViewModel : INotifyPropertyChanged
    {
        
        public ProductPriceViewModel() { }

        public event PropertyChangedEventHandler PropertyChanged;
        public event EventHandler? CanExecuteChanged;

        public void OnPropertyChanged([CallerMemberName] String info = "") =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(info));

        private bool Filter(object item)
        {
            Product p = item as Product;
            if (p == null) return true;
            var ret = true;
            if (!String.IsNullOrEmpty(MainProductSearch))
                ret = ret && p.Mainproduct.IndexOf(MainProductSearch, StringComparison.OrdinalIgnoreCase) >= 0 ||
                p.Name.IndexOf(MainProductSearch, StringComparison.OrdinalIgnoreCase) >= 0;
    
            return ret;
        }

        private CollectionViewSource cvs = new CollectionViewSource();
        public ICollectionView View { get; set; } 


        public ICommand MyCommand { get => new RelayCommand(executemethod, canexecutemethod); }


        string pricinglocalfile = @"C:\xmltest\Prices.txt";
        private void executemethod(object parameter)
        {
            switch (parameter.ToString())
            {
                
                case "ReadPricing": //to read local pricing file
                    cvs.Source = GetProductsPriceListXML();
                    return;
                    
                case "SaveFile":
                    data.Save("xxx.txt");
                    return;
                
                default:
                    MediaType = parameter.ToString();
                    break;
            }
            View.Refresh();
        }

        private static bool canexecutemethod(object obj) => true;


        XElement data;

        private List<Product> GetProductsPriceListXML()
        {
            var mylist = new List<Product>();

            data = XElement.Load(pricinglocalfile);
            foreach (XElement xe1 in data.Elements())
                if (xe1.Name == "Products")
                    foreach (var xe2 in xe1.Elements()) mylist.Add(new Product(xe2));
            return mylist;
        }


    }

Although I've not used it myself, reading through Microsoft documentation leads me to believe that CollectionView is actually a control that you can extend that allows you to manipulate a data collection within the UI without actually changing the data itself. It also doesn't appear to be used with DataGrid types but instead replaces them, specifically it expands upon or replaces ListView .

In this regard you need to bind your ItemSource to an actual data list eg, ObservableCollection<Product> , whether you use a DataGrid type or a CollectionView type within your UI.

Thus I would recommend that you change the following:

    private CollectionViewSource cvs = new CollectionViewSource();
    public ICollectionView View { get; set; } 

to

public ObservableCollection<Product> ProductList {get;set;}

This will automatically trigger a NotifyCollectionChanged when updated.

Then change:

case "ReadPricing": //to read local pricing file
    cvs.Source = GetProductsPriceListXML();
    return;

to

case "ReadPricing": //to read local pricing file
    ProductList.Clear();
    var list = GetProductsPriceListXML();
    foreach(var p in list)
    {
        ProductList.Add(p);
    }
    return;

or

case "ReadPricing": //to read local pricing file
    ProductList = new ObservableCollection<Product>(GetProductsPriceListXML());
    NotifyPropertyChanged("ProductList");
    return;

Then in your View

    ItemsSource="{Binding View}" AutoGenerateColumns="False" 

becomes

    ItemsSource="{Binding ProductList}" AutoGenerateColumns="False" 

I believe that if you then wished to manipulate the layout or content of your ProductList at run time you would need to replace your DataGrid with a CollectionView , bind it's ItemSource to ProductList , finally creating a ControlView that presents a CollectionView type property and manipulates the presentation of the data - examples to be found here

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