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;
}
}
CodePudding user response:
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 e.g., 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