Получить данные выбранной строки DataGrid в MVVM

132
08 июля 2019, 18:00

Как получить данные выбранной строки DataGrid в MVVM? Если я правильно понимаю, данные выбранной строки DataGrid попадают в SelectedProduct, а оттуда раздаются в TextBox. Кроме всего этого, мне нужно поотдельности получить элементы выбранной строки ProductName, ProductID, TotalSold (чтобы использовать их в других целях и классах). Пробовал таким образом: SelectedProduct.ProductName - не получается.

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
    public class ProductModel : INotifyPropertyChanged
    {
        private Int32 _ProductID;
        private String _ProductName;
        private Int32 _TotalSold;
        public Int32 TotalSold
        {
            get { return _TotalSold; }
            set
            {
                _TotalSold = value;
                OnPropertyChanged("TotalSold");
            }
        }
        public String ProductName
        {
            get { return _ProductName; }
            set
            {
                _ProductName = value;
                OnPropertyChanged("ProductName");
            }
        }
        public Int32 ProductID
        {
            get { return _ProductID; }
            set
            {
                _ProductID = value;
                OnPropertyChanged("ProductID");
            }
        }
        public ProductModel(Int32 productID, String productName, Int32 totalSold)
        {
            this.ProductID = productID;
            this.ProductName = productName;
            this.TotalSold = totalSold;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    public class ProductGridViewModel
    {
        private ProductModel _SelectedProduct;
        private ObservableCollection<ProductModel> _Products;
        public ObservableCollection<ProductModel> Products
        {
            get { return _Products; }
            set { _Products = value; }
        }
        public ProductModel SelectedProduct
        {
            get { return _SelectedProduct; }
            set { _SelectedProduct = value; }
        }
        public ProductGridViewModel()
        {
            Products = new ObservableCollection<ProductModel>();
            GenerateProducts();
        }
        private void GenerateProducts()
        {
            for (int x = 0; x < 100; x++)
            {
                this.Products.Add(new ProductModel(x, "Product #" + x, x + 50));
            }
        }
    }

<Window x:Class="MVVM.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:MVVM"
        Title="MainWindow" Height="350" Width="420" Background="Gray">
    <Window.Resources>
        <ViewModel:ProductGridViewModel x:Key="ProductViewModel"/>
    </Window.Resources>
    <Grid DataContext="{StaticResource ResourceKey=ProductViewModel}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <DataGrid 
            Width="500" 
            Grid.Column="0"
            AutoGenerateColumns="False"                        
            ItemsSource="{Binding Products}"
            SelectedItem="{Binding SelectedProduct, Mode=TwoWay}">
            <DataGrid.Columns>
                <DataGridTextColumn IsReadOnly="True"  Header="Product ID" Binding="{Binding ProductID, UpdateSourceTrigger=PropertyChanged}" />
                <DataGridTextColumn IsReadOnly="True"  Header="Product Name" Binding="{Binding ProductName, UpdateSourceTrigger=PropertyChanged}" />
                <DataGridTextColumn IsReadOnly="True"  Header="Total Sold" Binding="{Binding TotalSold, UpdateSourceTrigger=PropertyChanged}" />
            </DataGrid.Columns>
        </DataGrid>
        <StackPanel Height="100" Background="Wheat" Margin="10" Orientation="Vertical" Grid.Column="1">
            <TextBlock FontWeight="Bold" Width="100" TextWrapping="Wrap">Update your product info!</TextBlock>
            <TextBox Width="100" Text="{Binding SelectedProduct.ProductName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
            <TextBox Width="100" Text="{Binding SelectedProduct.TotalSold, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
    </Grid>
</Window>
Answer 1

Класс модели

public class ProductModel : INotifyPropertyChanged
{
    //INPC
    public event PropertyChangedEventHandler PropertyChanged;
    //ctor
    public ProductModel(Int32 productID, String productName, Int32 totalSold)
    {
        if (string.IsNullOrEmpty(productName))
        {
            throw new ArgumentException(nameof(productName));
        }
        ProductID = productID;
        ProductName = productName;
        TotalSold = totalSold;
    }
    private Int32 _TotalSold;
    public Int32 TotalSold
    {
        get { return _TotalSold; }
        set
        {
            _TotalSold = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TotalSold)));
        }
    }
    private String _ProductName;
    public String ProductName
    {
        get { return _ProductName; }
        set
        {
            _ProductName = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ProductName)));
        }
    }
    private Int32 _ProductID;
    public Int32 ProductID
    {
        get { return _ProductID; }
        set
        {
            _ProductID = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ProductID)));
        }
    }
}

Класс вьюмодели

public class ProductGridViewModel : INotifyPropertyChanged
{
    private readonly IMainWindow _mainWindow;
    //INPC
    public event PropertyChangedEventHandler PropertyChanged;
    //ctor
    public ProductGridViewModel(IMainWindow mainWindow)
    {
        this._mainWindow = mainWindow ??
            throw new ArgumentNullException(nameof(mainWindow));
        Products = new ObservableCollection<ProductModel>();
        GenerateProducts();
    }
    //--Properties
    /// <summary>
    /// Продукты
    /// </summary>
    private ObservableCollection<ProductModel> _Products;
    public ObservableCollection<ProductModel> Products
    {
        get { return _Products; }
        set
        {
            _Products = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Products)));
        }
    }

    /// <summary>
    /// Выбранный продукт
    /// </summary>
    private ProductModel _SelectedProduct;
    public ProductModel SelectedProduct
    {
        get { return _SelectedProduct; }
        set
        {
            _SelectedProduct = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedProduct)));
            ShowSelectedProductCommand.RaiseCanExecuteChanged(); //обновляем доступность кнопки
        }
    }
    //--Methods
    private void GenerateProducts()
    {
        for (int x = 0; x < 100; x++)
        {
            this.Products.Add(new ProductModel(x, "Product #" + x, x + 50));
        }
    }

    //--Commands
    private RelayCommand _ShowSelectedProductCommand;
    public RelayCommand ShowSelectedProductCommand
    {
        get => _ShowSelectedProductCommand
                = _ShowSelectedProductCommand ??
                    new RelayCommand(OnShowSelected, CanShowSelected);
    }
    private bool CanShowSelected()
    {
        if (SelectedProduct == null)
            return false;
        return true;
    }
    private void OnShowSelected()
    {
        string message = $"{SelectedProduct.ProductID}- {SelectedProduct.ProductName}";
        _mainWindow.ShowMessage(message);
    }
}

Xaml

<Grid x:Name="_gridProducts">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="300"/>
        <ColumnDefinition Width="100"/>
    </Grid.ColumnDefinitions>
    <DataGrid 
        Width="500" 
        Grid.Column="0"
        AutoGenerateColumns="False"                        
        ItemsSource="{Binding Products}"
        SelectedItem="{Binding SelectedProduct, Mode=TwoWay}">
        <DataGrid.Columns>
            <DataGridTextColumn IsReadOnly="True"  Header="Product ID" Binding="{Binding ProductID, UpdateSourceTrigger=PropertyChanged}" />
            <DataGridTextColumn IsReadOnly="True"  Header="Product Name" Binding="{Binding ProductName, UpdateSourceTrigger=PropertyChanged}" />
            <DataGridTextColumn IsReadOnly="True"  Header="Total Sold" Binding="{Binding TotalSold, UpdateSourceTrigger=PropertyChanged}" />
        </DataGrid.Columns>
    </DataGrid>
    <StackPanel Height="100" Background="Wheat" Margin="10" Orientation="Vertical" Grid.Column="1">
        <TextBlock FontWeight="Bold" Width="100" TextWrapping="Wrap">Update your product info!</TextBlock>
        <TextBox Width="100" Text="{Binding SelectedProduct.ProductName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <TextBox Width="100" Text="{Binding SelectedProduct.TotalSold, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <Button Content="Смотреть"
                Command="{Binding ShowSelectedProductCommand}"/>
    </StackPanel>
</Grid>

Кодбихайнд

public interface IMainWindow
{
    void ShowMessage(string message);
}
public partial class MainWindow : Window, IMainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        //
        var viewModel = new ProductGridViewModel(this);
        this._gridProducts.DataContext = viewModel;
    }
    public void ShowMessage(string message)
    {
        string caption = "Вы выбрали";
        MessageBox.Show(message, caption, MessageBoxButton.OK, MessageBoxImage.Information);
    }
}

Весь пример можно качнуть здесь

READ ALSO
Асинхронное выполнение задач PHP [закрыт]

Асинхронное выполнение задач PHP [закрыт]

Как сделать как на видео:

147
Как дороботать цикл для колонок Bootstrap?

Как дороботать цикл для колонок Bootstrap?

Цикл для колонок Bootstrap Суть цикла такова: если пост 3 или 6 закрывать но как сделать что когда постов 5 или 4 надо также зарывать (то есть как...

137
FTP php отображение списка названия файлов

FTP php отображение списка названия файлов

пытаюсь сделать отображение файлов с FTP сервера, но при разных вариациях, примерно одно и тоже сообщение bool(false)

127
Ajax form не работает.

Ajax form не работает.

Никак не могу решить проблему, всё перепробовалНа отдельном сайте работает, а тут нет

134