dataGrid列取决于另一列

时间:2015-10-20 01:41:22

标签: c# wpf mvvm binding datagrid

我正在研究WPF - MVVM应用程序。

我必须在空白InvoicedataGrid中添加产品。

每件商品都有参考号refsupdescription

当我在InvoicedataGrid中添加一行时,我会在ComboboxColumn中选择参考号,并且说明会显示在下一列中。

我该怎么做? 尝试保留MVVM模式

查看

<DataGrid x:Name="dataGridInvoice"
          Margin="5"
          Grid.Row="1"
          ItemsSource="{Binding Collection}"
          AutoGenerateColumns="False"
          SelectedItem="{Binding Selected, Mode=TwoWay}"
          SelectionMode="Extended"
          SelectionUnit="FullRow"
          AddingNewItem="dataGridInvoice_AddingNewItem">
    <DataGrid.Columns>
        <DataGridTextColumn Header="SuppNb"
                            Binding="{Binding suppInvNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                            Width="*" />
        <DataGridTextColumn Header="Supplier"
                            Binding="{Binding supplier, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                            Width="*" />
        <DataGridComboBoxColumn Header="Ref Supplier"
                                ItemsSource="{Binding Products, Mode=OneWay, Source={StaticResource supplier}}"
                                DisplayMemberPath="refsup"
                                SelectedValueBinding="{Binding refSupp}"
                                SelectedValuePath="refsup"
                                Width="*" />
        <DataGridTextColumn Header="Description"
                            Binding="{Binding description, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                            Width="*" />
    </DataGrid.Columns>
</DataGrid>

视图模型

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
}

模型

public partial class product
{
    public int idproduct { get; set; }
    public string @ref { get; set; }
    public int supplier { get; set; }
    public string refsup { get; set; }
    public string description { get; set; }
    public int MOQ { get; set; }
    public int unit { get; set; }
    public decimal priceMOQ { get; set; }

    public virtual foodSupplier foodSupplier { get; set; }
    public virtual unit unit1 { get; set; }
}
public partial class Invoice : ViewModelBase
{
    public int idInvoice { get; set; }
    public string suppInvNumber { get; set; }
    public Nullable<int> supplier { get; set; }
    public string refSupp { get; set; }
    public string description { get; set; }    

    public virtual foodSupplier foodSupplier { get; set; }
    public virtual shop shop1 { get; set; }
}

1 个答案:

答案 0 :(得分:0)

您可以创建DataGridTemplateColumn来定义CellTemplateCellEditingTemplate。可以根据所选值切换CellTemplate和CellEditingTemplate的DataTemplate中定义的控件的可见性。

但是,DataGridTemplateColumnor任何其他受支持的dataGrid列都不在DataGrid的Visual树中,因此默认情况下它不会继承DataGrid的DataContext。因为,它们不在同一个VisualTree中,因此任何使用RelativeSource获取DataContext的尝试都不会起作用,因为DataGrid将无法遍历到DataGrid。

因此,有各种方法可以实现这一目标;我将在下面展示一个:

  1. 创建FrameworkElement将继承DataContext,即使它们不在视觉或逻辑树中。所以,我们可以利用它来使用它。     

  2. 创建一个绑定到ProxyElement的ContentControl     

  3. 创建一个转换器,它将切换控件的可见性(在CellTemplate或CellEditingTemplate中定义)。

  4. 创建的代理元素可以绑定到Visibility DB。

    <Grid>
       <Grid.Resources>
         <FrameworkElement x:Key="ProxyElement" DataContext="{Binding}"></FrameworkElement>
       </Grid.Resources>
       <ContentControl Visibility="Collapsed" Content="{StaticResource ProxyElement}"></ContentControl>
       <DataGrid>
           <DataGrid.Columns>
            <DataGridTemplateColumn>
                 <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBox Visibility="{Binding Source={StaticResource ProxyElement}, Path=DataContext.refsub, Converter={StaticResource ConvertorToConvertrefsubToVisibility}}" />
                            </DataTemplate>
                 </DataGridTemplateColumn.CellTemplate>               
             </DataGridTemplateColumn>
            </DataGrid.Columns>
       </DataGrid>
    </Grid>