У меня проблема с моим приложением WPF MVVM. У меня есть представление (CaisseView.xaml) и его ViewModel (CaisseViewModel.cs, который используется как Datacontext для представления, вызванного с другой .cs). На мой взгляд, я использую itemsControl, чтобы иметь кнопку для каждого элемента наблюдаемой коллекции модели. Более того, на мой взгляд, у меня есть ListView. Я хочу, чтобы каждый раз, когда нажималась кнопка itemsControl, в моем Lisview появлялась новая строка. Это последнее, что это не работает! Используя debug, я ввожу в свою команду команду, добавляющую объект в мою наблюдаемую коллекцию, но приложение не актуализирует View.
В моей ViewModel я использую INotifyPropertyChanged, RelayCommand и ICommand.
Я дам тебе мой код. Можете ли вы помочь мне с моим вопросом ??? спасибо:
My View:
<UserControl x:Class="LMarket.Views.CaisseView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:LMarket.Views"
xmlns:localM="clr-namespace:LMarket.Models"
xmlns:localModel="clr-namespace:LMarket.ViewModels"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d">
<UserControl.Resources>
<localModel:CaisseViewModel x:Key="CaisseViewModel"/>
<localM:ProduitDuStock x:Key="ProduitDuStockModel"/>
</UserControl.Resources>
<Grid Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image Cursor="Hand" Source="/Resources/homepage.png" Width="32" Height="32" HorizontalAlignment="Left" Margin="15,10" Grid.Row="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding DataContext.OnHomeCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
<Image Cursor="Hand" Source="/Resources/LogOut.png" Width="32" Height="32" HorizontalAlignment="Right" Margin="15,10" Grid.Row="0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<i:InvokeCommandAction Command="{Binding DataContext.BackConnectionCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Image>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderThickness="2" BorderBrush="Azure" Margin="5,5,1,5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="1*" />
<RowDefinition Height="50" />
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#FFC2E0ED">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Image Cursor="Hand" VerticalAlignment="Center" Width="32" Height="32" Source="/Resources/files-and-folders.png"/>
<Image Cursor="Hand" VerticalAlignment="Center" Margin="10,0" Width="32" Height="32" Source="/Resources/cancel.png"/>
</StackPanel>
</Grid>
<ListView Grid.Row="1" Margin="5" SelectionMode="Single"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Path=LstProducts, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ListView.ItemTemplate>
<DataTemplate DataType="localM:ProduitDuStock">
<StackPanel Margin="2" MinWidth="244">
<StackPanel.Resources>
<Style TargetType="{x:Type StackPanel}">
<!-- <Style.Triggers>
<DataTrigger Binding="{Binding Path=Selected}" Value="True">
<Setter Property="Background" Value="LightBlue"/>
</DataTrigger>
</Style.Triggers> -->
</Style>
</StackPanel.Resources>
<DockPanel >
<TextBlock FontWeight="Bold" Text="Produit: " DockPanel.Dock="Left" Margin="5,0,5,0"/>
<TextBlock Text=" " />
<TextBlock Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Foreground="Green" FontWeight="Bold" />
</DockPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<DockPanel Grid.Row="2" Margin="5" Background="#FF296B88">
<Label Content="TOTAL" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" FontFamily="Rockwell Condensed" Foreground="#FFF2FF5A" />
<Label Content="$$" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="14" FontWeight="Bold" FontFamily="Rockwell Condensed" Foreground="#FFF2FF5A" />
</DockPanel>
<Grid Grid.Row="3" Background="#FFC2E0ED">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="2">
<Button Cursor="Hand" Width="80" Content="Cuenta %" Background="#FF98ADA8" BorderBrush="#FF4A6DFF" Margin="2,0">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Button.Resources>
</Button>
<Button Cursor="Hand" Width="80" Content="Producto %" Background="#FF98ADA8" BorderBrush="#FF4A6DFF" Margin="2,0">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Button.Resources>
</Button>
<Button Cursor="Hand" Width="80" Content="-1" Background="#FFDDCF00" BorderBrush="#FF4A6DFF" FontWeight="Bold" FontSize="20">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Button.Resources>
</Button>
<Button Cursor="Hand" Width="80" Content="+1" Background="#FF79C837" BorderBrush="#FF4A6DFF" FontWeight="Bold" FontSize="20" Margin="2,0">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Button.Resources>
</Button>
<Button Cursor="Hand" Width="auto" Content=" Validar para Pagar " Command="{Binding AddNewProductCommand}" Background="#FF98ADA8" BorderBrush="#FF4A6DFF" FontSize="19" Margin="80,0,2,0" Foreground="Black">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Button.Resources>
</Button>
</StackPanel>
</Grid>
</Grid>
</Border>
<Border Grid.Column="1" BorderThickness="2" BorderBrush="Azure" Margin="1,5,5,5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" MaxHeight="720"/>
<RowDefinition Height="1" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" Background="Transparent"
HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource="{Binding ListOfProducts}" MaxWidth="762">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Cursor="Hand" CornerRadius="8" Margin="4,3" BorderThickness="1.5" BorderBrush="#FFFDFF00">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF6F92DC" Offset="1"/>
<GradientStop Color="#FFA6DBFF" Offset="0.534"/>
</LinearGradientBrush>
</Border.Background>
<Button BorderBrush="Transparent" Background="Transparent" Command="{Binding Source={StaticResource CaisseViewModel}, Path=AddNewProductCommand}" CommandParameter="{Binding Id}">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="8"/>
</Style>
</Button.Resources>
<StackPanel Orientation="Vertical" Margin="2" Width="80" Height="80">
<Image Source="{Binding ProductImageUrl}" Width="40" Height="40" Margin="0,10,0,5"
HorizontalAlignment="Center"/>
<Label Content="{Binding Surname}" FontWeight="Bold" HorizontalAlignment="Center" FontSize="11"/>
</StackPanel>
</Button>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Border>
</Grid>
</Grid>
</UserControl>
И моя ViewModel:
using LMarket.Models;
using LMarket.Views;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Xml;
namespace LMarket.ViewModels
{
class CaisseViewModel : INotifyPropertyChanged
{
//Event for INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string str = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(str));
}
#region Attributs
private ObservableCollection<ProduitDuStock> listOfProducts;
private ObservableCollection<ProduitDuStock> lstProducts;
private ProduitDuStock selectedProduct;
#endregion
#region Getter/Setter
public ObservableCollection<ProduitDuStock> ListOfProducts
{
get
{
return listOfProducts;
}
set
{
if (listOfProducts != value)
{
listOfProducts = value;
}
NotifyPropertyChanged();
}
}
public ObservableCollection<ProduitDuStock> LstProducts
{
get
{
return lstProducts;
}
set
{
if (lstProducts != value)
{
lstProducts = value;
}
NotifyPropertyChanged();
}
}
public ProduitDuStock SelectedProduct
{
get
{
return selectedProduct;
}
set
{
if (selectedProduct != value)
{
selectedProduct = value;
NotifyPropertyChanged();
}
}
}
#endregion
#region Constructeur
public CaisseViewModel()
{
ListOfProducts = new ObservableCollection<ProduitDuStock>();
LstProducts = new ObservableCollection<ProduitDuStock>();
toto();
//Lecture du fichier ou son enregistrer les données du stock (En local sur un .xml)
try
{
//Ouverture du document XML
XmlDocument xmlDoc = new XmlDocument();
string Path = Directory.GetCurrentDirectory().ToString();
Path = Path + "\\Configuration\\Stockes.xml";
xmlDoc.Load(Path);
//Recupérer la section des produits
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/Stockes/Products/product");
//Pour chaque produit dans le fichier, créer un objet ProduitDuStock et l'ajouter à l'ObservableCollection.
foreach (XmlNode node in nodeList)
{
//Creation du nouvel objet
ProduitDuStock testProduit = new ProduitDuStock();
foreach (XmlAttribute att in node.Attributes)
{
//Récupération des parametres de l'objet.
switch (att.Name)
{
case "id":
testProduit.Id = int.Parse(att.Value);
break;
case "name":
testProduit.Name = att.Value;
break;
case "pays":
testProduit.Pays = att.Value;
break;
case "surname":
testProduit.Surname = att.Value;
break;
case "quantite":
testProduit.Quantite = int.Parse(att.Value);
break;
case "unitprice":
testProduit.UnitPrice = int.Parse(att.Value);
break;
case "productImageUrl":
testProduit.ProductImageUrl = att.Value;
break;
default:
break;
}
}
//Ajouter l'objet créé a notre ObservableCollection.
ListOfProducts.Add(testProduit);
}
}
catch (Exception ex)
{
}
}
#endregion
#region Command Definition
//Event RelayCommand Definition
private RelayCommand addProductToBill = null;
public ICommand AddProductToBill
{
get
{
if (addProductToBill == null)
{
addProductToBill = new RelayCommand(OnAddProductToBill);
}
return addProductToBill;
}
}
private RelayCommand addNewProductCommand = null;
public ICommand AddNewProductCommand
{
get
{
if (addNewProductCommand == null)
{
addNewProductCommand = new RelayCommand(OnAddNewProductCommand);
}
return addNewProductCommand;
}
}
#endregion
#region Command function definition
//Event lorsque le curseur rentre dans la zone du boutton "Stock"
private void OnAddNewProductCommand(object obj)
{
toto();
}
private void OnAddProductToBill(object obj)
{
toto();
}
#endregion
#region function
public void toto()
{
ProduitDuStock myAddProductToBill = new ProduitDuStock();
myAddProductToBill.Name = "trrt";
LstProducts.Add(myAddProductToBill);
}
#endregion
}
}
важная часть в представлении следующая:
<Button BorderBrush="Transparent" Background="Transparent" Command="{Binding Source={StaticResource CaisseViewModel}, Path=AddNewProductCommand}" CommandParameter="{Binding Id}">
помните, что эта кнопка определена в itemsControl! Поэтому Datacontextof кнопки не моя viewModel, поэтому я использую staticResource ...
Я надеюсь, что что-то мне поможет :) большое спасибо.