2015-10-02 138 views
2

我仍然是wpf - mvvm的初學者。我有一個數據網格綁定了一個集合。C#wpf,從文本框綁定到dataGridColumn

我需要填充我的文本框內容的第一列。 因此,每次我添加一個新行時,第一列應該已經有我的文本框的內容。

我該怎麼做?

查看:

<Grid DataContext="{Binding Source={StaticResource invoice}}"> 
    <StackPanel Orientation="Horizontal"> 
     <TextBox Width="71" 
       Name="InvoiveNumber" 
       Text="{Binding ??, Mode=OneWay}"> 
      <!-- My textbox --> 
     </TextBox> 
     <DatePicker></DatePicker> 
     <Label Content="Shop" /> 
     <ComboBox Margin="5" 
        ItemsSource="{Binding Collection, Source={StaticResource shop}}" 
        DisplayMemberPath="shop1" 
        Width="53" /> 
     <Label Content="Supplier" /> 
     <ComboBox Margin="5" 
        ItemsSource="{Binding Collection, Source={StaticResource supplier}}" 
        DisplayMemberPath="supplier" 
        SelectedItem="{Binding Selected, Source={StaticResource supplier}, Mode=TwoWay}" 
        Width="46" /> 
    </StackPanel> 
    <DataGrid x:Name="dataGridInvoice" 
       Margin="5" 
       Grid.Row="1" 
       ItemsSource="{Binding Collection}" 
       AutoGenerateColumns="False"> 
     <DataGrid.Columns> 
      <!-- My column --> 
      <DataGridTextColumn x:Name="dataGridTextColumn" 
           Header="Supplier Invoice Nb" 
           Binding="{Binding suppInvNumber, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
           Width="*" /> 
      <DataGridComboBoxColumn Header="Ref Supplier" 
            ItemsSource="{Binding Products, Source={StaticResource supplier}, Mode=TwoWay}" 
            DisplayMemberPath="refsup" 
            SelectedValueBinding="{Binding refSupp}" 
            SelectedValuePath="refsup" 
            Width="*" /> 
      <DataGridTextColumn Header="Quantity" 
           Binding="{Binding quantity, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
           Width="*" /> 
      <DataGridTextColumn Header="Prix/MOQ" 
           Binding="{Binding unitPrice, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
           Width="*" /> 
      <DataGridTextColumn Header="Total Price" 
           Binding="{Binding totalPrice, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
           Width="*" /> 
     </DataGrid.Columns> 
    </DataGrid> 
    <Button x:Name="BtnAdd" 
      Content="Save" 
      Command="{Binding SaveCommand}" 
      Margin="94,0" /> 
    </StackPanel> 
</Grid> 

視圖模型:所有的

public class InvoiceViewModel : ViewModelBase 
{ 
    public Context ctx = new Context(); 

    public InvoiceViewModel() 
    { 
     Get(false); 
    } 


    private ObservableCollection<Invoice> collection; 

    public ObservableCollection<Invoice> Collection 
    { 
     get 
     { 
      return collection; 
     } 
     set 
     { 
      collection = value; 
      OnPropertyChanged("Collection"); 
     } 
    } 


    private Invoice _selected; 
    public Invoice Selected 
    { 
     get 
     { 
      return _selected; 
     } 
     set 
     { 
      _selected = value; 
      OnPropertyChanged("Selected"); 
     } 
    } 

    private void Get(bool loadDataFirst) 
    { 
     if (loadDataFirst) ctx.Invoices.Load(); 
     Collection = ctx.Invoices.Local; 
    } 


    private void Save() 
    { 
     ctx.SaveChanges(); 
    } 

    private void Delete() 
    { 
     var id = Selected; 
     var invoice = (from i in ctx.Invoices 
        where i.idInvoice == id.idInvoice 
        select i).SingleOrDefault(); 

     Collection.Remove(invoice); 
    } 

    private Invoice _currentItem; 
    public Invoice CurrentItem 
    { 
     get 
     { 
      return _currentItem; 
     } 
     set 
     { 
      _currentItem = value; 
      OnPropertyChanged("CurrentItem"); 
     } 
    } 


    #region "Command" 

    private ICommand saveCommand; 
    private ICommand removeCommand; 

    public ICommand SaveCommand 
    { 
     get 
     { 
      return saveCommand ?? (saveCommand = new RelayCommand(p => this.Save(), p => this.CanSave())); 
     } 
    } 


    private bool CanSave() 
    { 
     return true; 
    } 

    public ICommand DeleteCommand 
    { 
     get 
     { 
      return removeCommand ?? (removeCommand = new RelayCommand(p => this.Delete(), p => this.CanDelete())); 
     } 
    } 

    public bool CanDelete() 
    { 
     if (Selected != null) 
      return true; 
     else 
      return false; 
    } 

    #endregion 

} 
+0

u能解釋什麼叫「應該在每個dataGridRow的第一列我寫在文本框中什麼」的意思...細說它多一點理解 –

+0

第一列?或您的StackPanel中的文本框?爲什麼你綁定到靜態資源而不是默認的DataContext(ViewModel)在你所有的stackpanel控件中?這真的是你想要做什麼? – cscmh99

+0

嘗試** Text =「{Binding CurrentItem.suppInvNumber}」> **對於TextBox,我猜測add函數會將CurrentItem存儲到數據庫並添加到Collection中。 – daniel

回答

0

我不得不改變以前的方法,因爲它只有在填充第一列時纔有效。 用下面的方法,我可以填寫四列。

private void dataGridInvoice_AddingNewItem(object sender, AddingNewItemEventArgs e) 
    { 

       DataGridRow newRow = (DataGridRow)dataGridInvoice.ItemContainerGenerator.ContainerFromIndex(dataGridInvoice.Items.Count - 1); 
       DependencyObject reference = newRow; 
       // MessageBox.Show(Convert.ToString(VisualTreeHelper.GetChildrenCount(reference))); 
       string invoiceNumber = null; 
       int _supplier = 0; 
       int _shop = 0; 
       DateTime _date = DateTime.Now; 


       if (newRow != null) 
       { 
        DataGridCellsPresenter presenter = GetVisualChildHelper<DataGridCellsPresenter>(newRow); 

        if (presenter == null) 
        { 
         dataGridInvoice.ScrollIntoView(newRow, dataGridInvoice.Columns[1]); 
         presenter = GetVisualChildHelper<DataGridCellsPresenter>(newRow); 
        } 

        DataGridCell cell0 = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(0); 
        DataGridCell cell1 = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(1); 
        DataGridCell cell2 = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(2); 
        DataGridCell cell3 = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(3); 

        invoiceNumber = InvoiceNumber.Text; 
        int value = Convert.ToInt32(shopComboBox.SelectedValue); 
        _shop = value; 

        value = Convert.ToInt32(supplierComboBox.SelectedValue); 
        _supplier = value; 

        _date = Convert.ToDateTime(datePicker.Text); 

        cell0.Content = invoiceNumber; 
        cell1.Content = _shop; 
        cell2.Content = _date; 
        cell3.Content = _supplier; 
       } 

       e.NewItem = new Invoice() { suppInvNumber = invoiceNumber, shop = _shop, supplier = _supplier, date = _date }; 

    } 


     public static T GetVisualChildHelper<T>(Visual parent) where T : Visual 
     { 
      T child = default(T); 
      int numVisuals = VisualTreeHelper.GetChildrenCount(parent); 
      for (int i = 0; i < numVisuals; i++) 
      { 
       Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); 
       child = v as T; 
       if (child == null) 
       { 
        child = GetVisualChildHelper<T>(v); 
       } 
       if (child != null) 
       { 
        break; 
       } 
      } 
      return child; 
     } 
3

首先,感謝這樣的具有挑戰性的問題。由於這個問題,我今天大量使用DataGrid。

問題解決後,花了一整天,並嘗試各種方法的完美解決方案。

在文本框中添加一些數字,然後單擊按鈕。該號碼將自動出現在任何新行中。只是在文本框中更改此數字不會帶來任何更改,因爲我不使用該方法。點擊按鈕是必須的。我可以禁用編輯第一列,但保持原樣。 該解決方案同樣適用,AutoGenerateColumns =「True」沒有任何更改。可用於

以下代碼是:

Window1.xaml

<Window x:Class="WpfDataControls.DataGrid.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="385.714" Width="598.872"> 

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="249*"/> 
     <RowDefinition Height="79*"/> 
    </Grid.RowDefinitions> 

    <TextBox x:Name="tbSupplierInvoiceNumber" HorizontalAlignment="Left" Height="23" Margin="168,10,0,0" Grid.Row="1" TextWrapping="Wrap" Text="1" VerticalAlignment="Top" Width="120"/> 
    <Button Content="Get invoices" HorizontalAlignment="Left" Margin="306,11,0,0" Grid.Row="1" VerticalAlignment="Top" Width="75" Click="Button_Click"/> 
    <DataGrid x:Name="dgrdInvoice" HorizontalAlignment="Left" Margin="10,10,0,0" AutoGenerateColumns="False" CanUserAddRows="True" 
       VerticalAlignment="Top" Height="229" Width="571" 
       LoadingRow="dgrdInvoice_LoadingRow"> 
     <DataGrid.Columns> 
      <!-- My column --> 
      <DataGridTextColumn x:Name="dataGridTextColumn" 
          Header="Supplier Invoice Nb" 
          Binding="{Binding suppInvNumber, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
          Width="*" /> 
      <DataGridTextColumn Header="Quantity" 
          Binding="{Binding quantity, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
          Width="*" /> 
      <DataGridTextColumn Header="Prix/MOQ" 
          Binding="{Binding unitPrice, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
          Width="*" /> 
      <DataGridTextColumn Header="Total Price" 
          Binding="{Binding totalPrice, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" 
          Width="*" /> 
     </DataGrid.Columns> 
    </DataGrid> 
    <TextBlock HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" TextWrapping="Wrap" Text="Initial suppInvNumber" VerticalAlignment="Top" Width="140"/> 
    <TextBlock HorizontalAlignment="Left" Margin="111,38,0,0" Grid.Row="1" TextWrapping="Wrap" Text="Change this number and click get invoices to see the change" VerticalAlignment="Top"/> 

</Grid>  
    </Window> 

Window1.xaml.cs

using System; 
using System.Collections.ObjectModel; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Media; 
using System.Diagnostics; 

namespace WpfDataControls.DataGrid 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    {  
     public Window1() 
     { 
      InitializeComponent(); 

      dgrdInvoice.AddingNewItem += dgrdInvoice_AddingNewItem; 
     }  

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      ViewModel vm = new ViewModel(); 
      dgrdInvoice.ItemsSource = vm.InvoiceCollection; 
     } 

     #region Grid events 
      void dgrdInvoice_LoadingRow(object sender, DataGridRowEventArgs e) 
      { 
       e.Row.Loaded += dgrdInvoice_Row_Loaded;     
      } 

      void dgrdInvoice_Row_Loaded(object sender, RoutedEventArgs e) 
      { 
       DataGridRow newRow = ((DataGridRow)sender); 

       if (newRow.GetIndex() == dgrdInvoice.Items.Count - 1) 
       { 
        newRow.Background = new SolidColorBrush(Colors.BlanchedAlmond); 
        DependencyObject reference = newRow; 

        while (true) 
        { 
         reference = VisualTreeHelper.GetChild(reference, 0); 
         if (reference is TextBlock) 
         { 
          TextBlock f = (TextBlock)reference; 
          f.Text = Convert.ToInt32(tbSupplierInvoiceNumber.Text).ToString(); 
          break; 
         } 
        } 
       } 
      } 

      void dgrdInvoice_AddingNewItem(object sender, AddingNewItemEventArgs e) 
      { 
       DataGridRow newRow = (DataGridRow)dgrdInvoice.ItemContainerGenerator.ContainerFromIndex(dgrdInvoice.Items.Count - 1); 
       DependencyObject reference = newRow; 
       int invoiceNumber; 
       while (true) 
       { 
        reference = VisualTreeHelper.GetChild(reference, 0); 
        if (reference is TextBlock) 
        { 
         invoiceNumber = Convert.ToInt32(tbSupplierInvoiceNumber.Text); 
         TextBlock f = (TextBlock)reference; 
         f.Text = invoiceNumber.ToString(); 
         break; 
        } 
       } 

       e.NewItem = new Invoice() { suppInvNumber = invoiceNumber }; 
      }  
     #endregion 

    } 

    public class ViewModel 
    { 
     ObservableCollection<Invoice> _invoiceCollection; 
     public ObservableCollection<Invoice> InvoiceCollection { get { return _invoiceCollection; } } 

     public ViewModel() 
     { 
      _invoiceCollection = new ObservableCollection<Invoice>(); 

      _invoiceCollection.Add(new Invoice() { suppInvNumber = 1, quantity=120, unitPrice=23, totalPrice=56 }); 
      _invoiceCollection.Add(new Invoice() { suppInvNumber = 3, quantity = 122, unitPrice = 13, totalPrice = 23 }); 
      _invoiceCollection.Add(new Invoice() { suppInvNumber = 4, quantity = 234, unitPrice = 10, totalPrice = 43 }); 
      _invoiceCollection.Add(new Invoice() { suppInvNumber = 6, quantity = 512, unitPrice = 35, totalPrice = 67 }); 
      _invoiceCollection.Add(new Invoice() { suppInvNumber = 7, quantity = 612, unitPrice = 3, totalPrice = 120 }); 
     } 
    } 

    public class Invoice 
    { 
     public int suppInvNumber { get; set; } 
     public int quantity { get; set; } 
     public int unitPrice { get; set; } 
     public int totalPrice { get; set; } 
    } 
} 
+0

非常感謝你,我會在星期一嘗試。 – Cantinou

+0

它工作正常,非常感謝;) – Cantinou

+0

,如果我想把另一個文本框的值放在第二列,我該怎麼辦? – Cantinou