如何绑定一个DataGrid行与WPF MVVM文本框中

问题描述:

我有一个包含一些产品详情DataGrid中,我需要的产品的详细信息加载到一些文本框,当我双击DataGrid中的某一特定产品。

I have a DataGrid which contains some Product details , i need to load the product details into some textboxes when i double click on a particular product in the datagrid.

先谢谢了。

欢迎到计算器!通常人们不会回答没有下列问题。

Welcome to *! Usually people won't answer questions without the following.


  • 您正在试图做的清晰总结。

  • 所有相关的code

  • 您遇到任何异常

  • 所有你为了使用的研究联系,以获得你在哪里

不过,我会给你你问了演示。

That said, I will give you a demo of what you're asking for.

下面是XAML

<Window x:Class="datagriddemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:datagriddemo"
        Title="MainWindow" Height="350" Width="420" Background="Gray">

    <!--This is where we define the resource that the XAML here is going to
    use. As you can see, I am importing our view model-->
    <Window.Resources>
        <ViewModel:ProductGridViewModel x:Key="ProductViewModel"/>
    </Window.Resources>


    <!--This is the main layout of the XAML. In the Grid below,
    I set the "DataContext" to our static resource we just defined above.
    What this does is tell everyone inside this grid, "If you don't define
    your own data context, you're going to use mine" Because of this, all
    of the elements inside this grid will have access to the public properties
    of the ViewModel-->
    <Grid DataContext="{StaticResource ResourceKey=ProductViewModel}">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>

        <!-- This is the datagrid that we are displaying. The two important things
        to note here are "ItemsSource" and "SelectedItem". "ItemsSource" is the collection
        that we want to display in our grid. This is where are product models are stored.
        SelectedProduct is going to be where the selected grid row is stored so we can
        access its data with the text boxes defined below. -->
        <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>

        <!-- This stack panel contains the text boxes we are going to use to edit our data. Notice that the 
        bindings point to SelectedProduct.Property. This is because we are accessing properties inside of 
        the SelectedProduct property in our ViewModel. When we edit these text boxes the data in the grid
        will automatically change. -->
        <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>

接下来是我们的视图模型。如果视图是蛋糕上的糖霜,那么你可以认为视图模型围绕布丁蛋糕。您的视图模型是你的逻辑住在哪里。它会做整理,运算和其他的东西。

Next is our ViewModel. If the view is the frosting on the cake then you can think of the view model as the cake around the pudding. Your view model is where your logic lives. It will do sorting, crunching and other stuff.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace datagriddemo
{
    public class ProductGridViewModel
    {
        private ProductModel _SelectedProduct;
        private ObservableCollection<ProductModel> _Products;


        /// <summary>
        /// Notice that though this updates the grid as you
        /// add or remove elements, it doesn't call onproperty
        /// changed in the setter... Magic? Nope, Observable
        /// collections call OnPropertyChanged for you.
        /// 
        /// Caveat: They will NOT call on property changed
        /// for you if you do Products = new ObservableCollection...
        /// Only when you do Products.Add(yourProduct)...
        /// </summary>
        public ObservableCollection<ProductModel> Products
        {
            get { return _Products; }
            set { _Products = value; }
        }



        /// <summary>
        /// This is the selected row in the grid. It automatically changes
        /// when you select new rows because we set the grid SelectedItem property 
        /// to Mode=TwoWay
        /// </summary>
        public ProductModel SelectedProduct
        {
            get { return _SelectedProduct; }
            set { _SelectedProduct = value; }
        }


        /// <summary>
        /// View Models constructor. It get's called automatically when the view 
        /// is initialized because we declared it as a static resource in the XAML.
        /// </summary>
        public ProductGridViewModel()
        {
            //DONT FORGET TO NEW UP YOUR OBSERVABLE COLLECTIONS!! 
            Products = new ObservableCollection<ProductModel>();

            //Don't forget to generate the data!
            GenerateProducts();
        }

        /// <summary>
        /// Use this method to generate dummy data
        /// </summary>
        private void GenerateProducts()
        {
            for (int x = 0; x < 100; x++)
            {

                this.Products.Add(new ProductModel(x,"Product #"+x,x+50));
            }
        }

    }
}

终于有你的模型。这是你的实际数据。这一点,是的,这是你的布丁。

Finally there is your Model. This is your actual data. This, yes this, is your pudding.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace datagriddemo
{
    public class ProductModel : INotifyPropertyChanged
    {
        private Int32 _ProductID;
        private String _ProductName;
        private Int32 _TotalSold;


        /// <summary>
        /// Note for the properties below:
        /// Notice that first, the property names match those bound in the XAML
        /// This is all part of the grand scheme.
        /// 
        /// When the OnProperty changed is called, the UI knows to go search for
        /// those properties. It's important that these all have the correct spelling
        /// and casing.
        /// </summary>

        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");
            }
        }


        /// <summary>
        /// Just a normal constructor to load up our properties.
        /// </summary>
        /// <param name="productID"></param>
        /// <param name="productName"></param>
        /// <param name="totalSold"></param>
        public ProductModel(Int32 productID, String productName, Int32 totalSold)
        {
            this.ProductID = productID;
            this.ProductName = productName;
            this.TotalSold = totalSold;
        }

        /// <summary>
        /// This is for updating the UI
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// When a property changes in this object, if you want it reflected on the 
        /// UI you need to call this function
        /// </summary>
        /// <param name="propertyName"></param>
        public void OnPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

最后在这里是预期的结果。

Finally here is the expected result

在我们看到我们的网格装起来的新数据这第一图片

In this first image we see our grid loaded up with its new data

如果你点击一排,你会看到它的数据填充侧面的两个文本框。

If you click on a row you will see it's data populate the two text boxes on the side.

最后,如果您更改文本框中的数据,你会看到它在网格立即更新。

Finally if you change the data in the text boxes you will see it update in the grid immediately.

这就是它!一个完整的数据网格MVVM到文本框和背部的解决方案。希望这可以帮助。请记住我说的什么,从你预期的那样的问题提问者和乐趣!欢迎到WPF和MVVM。

And that's it! A complete MVVM datagrid to text box and back solution. Hope this helps. Please remember what I said about what is expected from you as a question asker and have fun! Welcome to WPF and MVVM.