Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从datagrid、WPF添加和检索数据_Wpf_C# 4.0_Datagrid_Wpf Controls_Wpfdatagrid - Fatal编程技术网

从datagrid、WPF添加和检索数据

从datagrid、WPF添加和检索数据,wpf,c#-4.0,datagrid,wpf-controls,wpfdatagrid,Wpf,C# 4.0,Datagrid,Wpf Controls,Wpfdatagrid,我想在点击按钮时向datagrid添加数据。假设一个数据网格有3个标题,即ITEM、QUANTITY、PRICE。现在,当用户第一次单击时,我会像这样获取第一行中的数据 1 1 1 然后,在第二次单击时,将显示总数据 1 1 1 2 2 2 等等 1 1 1 2 2 2 3 3 3 4 4 4 . . . . . . . . . . . . n n n 当我点击一个按钮,比如说数组,我应该在ar

我想在点击按钮时向datagrid添加数据。假设一个数据网格有3个标题,即ITEM、QUANTITY、PRICE。现在,当用户第一次单击时,我会像这样获取第一行中的数据

1   1   1
然后,在第二次单击时,将显示总数据

1   1   1
2   2   2
等等

1   1   1
2   2   2
3   3   3
4   4   4
.   .   .
.   .   .
.   .   .
.   .   .
n   n   n

当我点击一个按钮,比如说数组,我应该在arraylist中获取datagrid数据。这在WPF中可能吗??我已经在使用jquery和后端方法的web应用程序中这样做了。无论如何,我希望这将是容易的WPF也。我在网上搜索过,但所有的例子似乎都与数据绑定有关,我不想做数据绑定,我想用我试图在上面解释的简单方法,希望它清晰明了。

我同意两位评论者的观点,数据绑定是实现这一点的方法,我知道一开始它看起来很复杂,但是一旦你得到一个很好的转换器和命令库,它可以一次又一次地被重用,上面一个简单的数据绑定示例就是这样的

1   1   1
XAML,创建一个新项目,然后在主窗口中粘贴此代码,它所做的只是添加一个包含3列的数据网格和一个将添加新行的按钮。请注意,此窗口的数据上下文设置为自身,这意味着类MainWindow上的属性在默认情况下将以{Binding}公开

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" Margin="432,289,0,0" VerticalAlignment="Top" Width="75" Command="{Binding AddCommand}"/>
        <DataGrid HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="274" Width="497" AutoGenerateColumns="False" ItemsSource="{Binding Items}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Field1}"/>
                <DataGridTextColumn Binding="{Binding Field2}"/>
                <DataGridTextColumn Binding="{Binding Field3}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
最后是命令类,它可以在所有项目中反复使用,以将某些内容链接到代码隐藏

public class SimpleCommand : DependencyObject, ICommand
{
    readonly Action<object> _execute;
    readonly Func<object, bool> _canExecute;
    public event EventHandler CanExecuteChanged;

    public SimpleCommand(Action<object> execute, Func<object, bool> canExecute = null)
    {
        _canExecute = canExecute == null ? parmeter => { return true; } : canExecute;
        _execute = execute;
    }
    public virtual void Execute(object parameter)
    {
        _execute(parameter);
    }
    public virtual bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }
}
公共类SimpleCommand:DependencyObject,ICommand
{
只读操作_执行;
只读功能可执行;
公共事件处理程序CanExecuteChanged;
公共SimpleCommand(Action execute,Func canExecute=null)
{
_canExecute=canExecute==null?参数=>{return true;}:canExecute;
_执行=执行;
}
公共虚拟空执行(对象参数)
{
_执行(参数);
}
公共虚拟布尔CanExecute(对象参数)
{
返回_canExecute==null?true:_canExecute(参数);
}
}

为了展示通过数据绑定实现这一点是多么容易,我很快开发了这个小应用程序。这花了我大约10分钟的时间,但是使用Resharper和其他工具的更有经验的程序员可以在几分钟内完成这项工作

这是我的InventoryItemViewModel.cs

public class InventoryItemViewModel : ViewModelBase
{
    private int _itemid;

    public int ItemId
    {
        get { return _itemid; }
        set { _itemid = value; this.OnPropertyChanged("ItemId"); }
    }

    private int _qty;

    public int Qty
    {
        get { return _qty; }
        set { _qty = value; this.OnPropertyChanged("Qty"); }
    }
    private int _price;

    public int Price
    {
        get { return _price; }
        set { _price = value; this.OnPropertyChanged("Price"); }
    }

}
public class MainWindowViewModel : ViewModelBase
{
    public MainWindowViewModel()
    {
        this.InventoryCollection = new ObservableCollection<InventoryItemViewModel>();
        this.AddItemCommand = new DelegateCommand((o) => this.AddItem());
        this.GetItemListCommand = new DelegateCommand((o) => this.GetInventoryItemList());
    }

    public ICommand AddItemCommand { get; private set; }
    public ICommand GetItemListCommand { get; private set; }

    public ObservableCollection<InventoryItemViewModel> InventoryCollection { get; private set; }

    private void AddItem()
    {
        // get maxid in collection
        var maxid = InventoryCollection.Count;
        // if collection is not empty get the max id (which is the same as count in this case but whatever)
        if (maxid > 0) maxid = InventoryCollection.Max(x => x.ItemId);

        InventoryCollection.Add(new InventoryItemViewModel
        {
            ItemId = ++maxid,
            Price = maxid,
            Qty = maxid
        });
    }

    private List<InventoryItemViewModel> GetInventoryItemList()
    {
        return this.InventoryCollection.ToList();
    }
}
正如你所看到的,没有太多,只有你的3个属性。实现简单UI更新的神奇之处在于我实现了ViewModelBase

这里是ViewModelBase.cs

/// <summary>
/// Abstract base to consolidate common functionality of all ViewModels
/// </summary>
public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
        {
            handler(this, e);
        }
    }
}

嗯,IMHO
数据绑定是WPF和SL中最简单的方法。^^是的,数据绑定是最简单的方法。否则,每次更改数据时,您必须编写自己的逻辑来更新datagrid。还有数据绑定,这意味着您将有一个绑定到datagrid的itemssource属性的集合。你可以很容易地调用集合上的ToArray()或ToList()方法来提取结果。我猜你在写我的lol时,它们几乎是相同的——可能是lol!我花了好长时间才把答案贴出来,但还是有些疯狂的延迟!我的数据库是mysql:(,这可以实现吗?您在关于数据库的问题中没有提到。数据库如何与您的问题交互?有几种方法可以读取和写入mysql数据库中的数据。下面是一个链接,说明如何使用实体框架。很抱歉,我没有提到mysql,无论如何,我仍然希望摆脱数据绑定,因为我不知道如何使用实体框架ant想查看数据库中的数据,相反,我想在运行时单击按钮手动添加数据,即值也可以来自用户输入,稍后按其他键时,我想在数据库中插入数据,直到那时,只有用户才能从datagrid中添加或删除数据。希望成为替补,感谢您的努力
public class MainWindowViewModel : ViewModelBase
{
    public MainWindowViewModel()
    {
        this.InventoryCollection = new ObservableCollection<InventoryItemViewModel>();
        this.AddItemCommand = new DelegateCommand((o) => this.AddItem());
        this.GetItemListCommand = new DelegateCommand((o) => this.GetInventoryItemList());
    }

    public ICommand AddItemCommand { get; private set; }
    public ICommand GetItemListCommand { get; private set; }

    public ObservableCollection<InventoryItemViewModel> InventoryCollection { get; private set; }

    private void AddItem()
    {
        // get maxid in collection
        var maxid = InventoryCollection.Count;
        // if collection is not empty get the max id (which is the same as count in this case but whatever)
        if (maxid > 0) maxid = InventoryCollection.Max(x => x.ItemId);

        InventoryCollection.Add(new InventoryItemViewModel
        {
            ItemId = ++maxid,
            Price = maxid,
            Qty = maxid
        });
    }

    private List<InventoryItemViewModel> GetInventoryItemList()
    {
        return this.InventoryCollection.ToList();
    }
}
public class DelegateCommand : ICommand
{
    /// <summary>
    /// Action to be performed when this command is executed
    /// </summary>
    private Action<object> executionAction;

    /// <summary>
    /// Predicate to determine if the command is valid for execution
    /// </summary>
    private Predicate<object> canExecutePredicate;

    /// <summary>
    /// Initializes a new instance of the DelegateCommand class.
    /// The command will always be valid for execution.
    /// </summary>
    /// <param name="execute">The delegate to call on execution</param>
    public DelegateCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Initializes a new instance of the DelegateCommand class.
    /// </summary>
    /// <param name="execute">The delegate to call on execution</param>
    /// <param name="canExecute">The predicate to determine if command is valid for execution</param>
    public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        this.executionAction = execute;
        this.canExecutePredicate = canExecute;
    }

    /// <summary>
    /// Raised when CanExecute is changed
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Executes the delegate backing this DelegateCommand
    /// </summary>
    /// <param name="parameter">parameter to pass to predicate</param>
    /// <returns>True if command is valid for execution</returns>
    public bool CanExecute(object parameter)
    {
        return this.canExecutePredicate == null ? true : this.canExecutePredicate(parameter);
    }

    /// <summary>
    /// Executes the delegate backing this DelegateCommand
    /// </summary>
    /// <param name="parameter">parameter to pass to delegate</param>
    /// <exception cref="InvalidOperationException">Thrown if CanExecute returns false</exception>
    public void Execute(object parameter)
    {
        if (!this.CanExecute(parameter))
        {
            throw new InvalidOperationException("The command is not valid for execution, check the CanExecute method before attempting to execute.");
        }
        this.executionAction(parameter);
    }
<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ctlDefs="clr-namespace:WpfApplication1"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>

</Window.Resources>

<StackPanel>
    <Button Command="{Binding Path=GetItemListCommand}" Content="Get Item List" />
    <Button Command="{Binding Path=AddItemCommand}" Content="Add Item" />
    <DataGrid ItemsSource="{Binding Path=InventoryCollection}" />
</StackPanel>
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        var mainvm = new MainWindowViewModel();
        var window = new MainWindow
        {
            DataContext = mainvm
        };
        window.Show();
    }
}