2013-03-15 82 views
0

我想添加按鈕點擊數據到數據網格。假設一個包含3個頭的數據網格,即ITEM,QUANTITY,PRICE。現在,當用戶第一次點擊時,我會像這樣在第一行中獲取數據。從數據網格添加和回收數據,WPF

1 1 1 

然後在第二次點擊的總數據將

1 1 1 
2 2 2 

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

,當我點擊一個按鈕,說陣列,我應該得到的數組列表數據網格數據。這是可能的WPF?我已經在使用jquery和後端方法的web應用程序中完成了這項工作。無論如何,我希望這在WPF中也很容易。我搜索了網絡,但所有的例子似乎都與數據綁定的複雜性,我不想做數據綁定,並希望與我試圖解釋上面的簡單方法,希望其清晰。任何幫助將不勝感激。

感謝您

+0

那麼恕我直言,'DataBinding'是WPF和SL最簡單的方法。^^ – DHN 2013-03-15 08:10:23

+0

是數據綁定將是做到這一點的最簡單方法。否則,每次更改數據時,都必須編寫自己的邏輯來更新數據網格。對於數據綁定,這意味着您將有一個綁定到datagrid的itemssource屬性的集合。您可能可以非常輕鬆地在集合上調用ToArray()或ToList()方法來提取結果。 – failedprogramming 2013-03-15 08:16:09

回答

0

我打算與兩個評論者同意,綁定是的方式做到這一點,我知道它看起來起初非常複雜,但一旦你轉換的一個很好的圖書館和命令一起它可以一次又一次地重複使用,上面的一個簡單的數據綁定例子看起來像這樣。

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> 

現在後面的代碼主窗口,在這裏我已經創建了一個我們可以綁定2個屬性,一個是它包含的會出現什麼作爲行,另一種是可以被稱爲命令的數組項添加另一行。

這裏的ObservableCollection有方法告訴綁定引擎何時更改行,所以你不必費心更新自己的網格。

public partial class MainWindow : Window 
    { 
     public ObservableCollection<Item> Items 
     { 
      get { return (ObservableCollection<Item>)GetValue(ItemsProperty); } 
      set { SetValue(ItemsProperty, value); } 
     } 
     public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof(ObservableCollection<Item>), typeof(MainWindow), new PropertyMetadata(null)); 

     public SimpleCommand AddCommand 
     { 
      get { return (SimpleCommand)GetValue(AddCommandProperty); } 
      set { SetValue(AddCommandProperty, value); } 
     } 
     public static readonly DependencyProperty AddCommandProperty = DependencyProperty.Register("AddCommand", typeof(SimpleCommand), typeof(MainWindow), new PropertyMetadata(null)); 

     public MainWindow() 
     { 
      InitializeComponent(); 
      Items = new ObservableCollection<Item>(); 
      AddCommand = new SimpleCommand(para => 
      { 
       string nextNumber = Items.Count.ToString(); 
       Items.Add(new Item() { Field1 = nextNumber, Field2 = nextNumber, Field3 = nextNumber }); 
      }); 
     } 
    } 

Item類,這只是一個非常簡單的類,它有符合您的數據網格,字段1這3個屬性,2 & 3這裏的依賴屬性也意味着你不必費心更新網格當數據改變時你自己。

public class Item : DependencyObject 
{ 
    public string Field1 
    { 
     get { return (string)GetValue(Field1Property); } 
     set { SetValue(Field1Property, value); } 
    } 
    public static readonly DependencyProperty Field1Property = DependencyProperty.Register("Field1", typeof(string), typeof(Item), new PropertyMetadata(null)); 

    public string Field2 
    { 
     get { return (string)GetValue(Field2Property); } 
     set { SetValue(Field2Property, value); } 
    } 
    public static readonly DependencyProperty Field2Property = DependencyProperty.Register("Field2", typeof(string), typeof(Item), new PropertyMetadata(null)); 

    public string Field3 
    { 
     get { return (string)GetValue(Field3Property); } 
     set { SetValue(Field3Property, value); } 
    } 
    public static readonly DependencyProperty Field3Property = DependencyProperty.Register("Field3", typeof(string), typeof(Item), new PropertyMetadata(null)); 
} 

最後的命令類,這是可以一遍又一遍地重複使用在所有項目的鏈接的東西后面的代碼。

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); 
    } 
} 
+0

我的數據庫是mysql :( – Aadam 2013-03-15 09:25:53

+0

對不起,我沒有提到有關mysql,無論如何,我仍然想從數據綁定中逃離,因爲我不想從數據庫中查看數據,而是我想在運行時按鈕單擊手動添加數據,即值也可以來自用戶輸入,稍後在其他按鍵時我想在該時間點插入數據到數據庫,直到那時用戶應該只能從數據網格添加或刪除數據。爲你的努力 – Aadam 2013-03-15 14:59:46

0

爲了說明使用DataBinding實現這種操作非常簡單,我很快打開了這個小應用程序。這花了我大約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"); } 
    } 

} 

正如你可以看到有沒有太多的話,只是你的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); 
     } 
    } 
} 

你幾乎可以複製這個類所有的WPF項目,並以此作爲它。

這裏是我的主窗口中的視圖模型:MainWindowViewModel.cs

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

正如你所看到的,我有InventoryItemViewModels的一個ObservableCollection。這是我從我的用戶界面綁定的集合。您必須使用ObservableCollection而不是List或數組。爲了讓按鈕起作用,我定義了ICommand屬性,然後綁定到UI中的按鈕。我使用DelegateCommand類將動作重定向到相應的私有方法。

這裏是DelegateCommand.cs,這是另一個類,你可以在你的WPF項目中包含並且信任它工作。

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

而且我MainWindow.xaml我的UI代碼如下所示:

<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> 

要膠水都在一起,我重寫App.xaml.cs OnStartUp方法。

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(); 
    } 
} 
+0

猜你在寫我的時候寫了我的哈哈,他們幾乎完全相同 – Andy 2013-03-15 08:59:00

+0

是的可能哈哈!我花了很多時間來發布答案,有一些瘋狂的滯後! – failedprogramming 2013-03-15 09:02:54

+0

我的數據庫是mysql :(,can這是可以實現的 – Aadam 2013-03-15 09:26:09