WPF-MVVM 数据网格的 ComboBoxColumn 问题
ComboBoxColumn Issue with WPF-MVVM datagrid
我想在我的数据网格 "Product" 中添加一个包含供应商列表的 ComboBox 列。但我所做的一切都不起作用。绑定此列的好方法是什么?
模特们:
public partial class foodSupplier
{
public foodSupplier()
{
this.products = new HashSet<product>();
}
public int idfoodSupplier { get; set; }
public string supplier { get; set; }
public virtual ICollection<product> products { get; set; }
}
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; }
}
这是我的命令库(ViewModel):
public class CommandBase<T> :INotifyPropertyChanged
{
#region "INotifyPropertyChanged members"
public event PropertyChangedEventHandler PropertyChanged;
//This routine is called each time a property value has been set.
//This will //cause an event to notify WPF via data-binding that a change has occurred.
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private ObservableCollection<T> collection;
public ObservableCollection<T> Collection
{
get
{
if (collection == null)
{
collection = new ObservableCollection<T>();
}
return collection;
}
set { collection = value; OnPropertyChanged("Collection");}
}
private ICommand getCommand;
private ICommand saveCommand;
private ICommand removeCommand;
public ICommand GetCommand
{
get
{
return getCommand ?? (getCommand = new RelayCommand(param => Get(),param=>CanGet()));
}
}
protected virtual bool CanGet()
{
return true;
}
public ICommand SaveCommand
{
get
{
return saveCommand ?? (saveCommand = new RelayCommand(param => Save()));
}
}
protected virtual bool CanSave()
{
return true;
}
public ICommand DeleteCommand
{
get
{
return removeCommand ?? (removeCommand = new RelayCommand(param=>Delete()));
}
}
protected virtual bool CanDelete()
{
return true;
}
}
这里是 ProductViewModel:
public class ProductViewModel : CommandBase<product>
{
public Context ctx = new Context();
protected override void Get()
{
ctx.products.ToList().ForEach(supplier => ctx.products.Local.Add(supplier));
Collection = ctx.products.Local;
}
protected override bool CanGet()
{
return true;
}
protected override void Save()
{
foreach (product item in Collection)
{
if (ctx.Entry(item).State == System.Data.Entity.EntityState.Added)
{
ctx.products.Add(item);
}
}
ctx.SaveChanges();
}
}
}
这里是 SupplierViewModel:
public class SupplierViewModel : CommandBase<foodSupplier>
{
public Context ctx = new Context();
protected override void Get()
{
ctx.foodSuppliers.ToList().ForEach(supplier => ctx.foodSuppliers.Local.Add(supplier));
Collection = ctx.foodSuppliers.Local;
}
protected override bool CanGet()
{
return true;
}
protected override void Save()
{
foreach (foodSupplier item in Collection)
{
if (ctx.Entry(item).State == System.Data.Entity.EntityState.Added)
{
ctx.foodSuppliers.Add(item);
}
}
ctx.SaveChanges();
}
}
这里的观点:
<Page.Resources>
<vm:ProductViewModel x:Key="product"/>
<vm:SupplierViewModel x:Key="supplier"/>
</Page.Resources>
<Grid DataContext="{Binding Source={StaticResource product}}">
<StackPanel Grid.ColumnSpan="2" Margin="0,0,58,0">
<Button x:Name="BtnDelete"
Content="Delete"
Command="{Binding DeleteCommand}"/>
<Button x:Name="BtnAdd"
Content="Save"
Command="{Binding SaveCommand}"/>
<DataGrid x:Name="dataGrid" Margin="5" ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="id" Binding="{Binding idproduct, UpdateSourceTrigger=PropertyChanged}" Visibility="Hidden"/>
<DataGridTextColumn Header="Ref FTHK" Binding="{Binding ref, UpdateSourceTrigger=PropertyChanged}" />
<DataGridComboBoxColumn Header="Supplier" ItemsSource="{Binding Collection, Source={StaticResource supplier}}????" DisplayMemberPath="supplier" SelectedValueBinding="{Binding ????}" SelectedValuePath="idSupplier"/>
<DataGridTextColumn Header="Ref Supplier" Binding="{Binding refsup, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Description" Binding="{Binding description, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="MOQ" Binding="{Binding MOQ, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Unit" Binding="{Binding unit, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Prix/MOQ" Binding="{Binding priceMOQ, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding GetCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
</StackPanel>
</Grid>
您必须像加载产品一样加载 SupplierCollection。我更喜欢随需应变的概念。类似于下面的代码
public class CommandBase<T> : INotifyPropertyChanged
{
#region "INotifyPropertyChanged members"
public event PropertyChangedEventHandler PropertyChanged;
//This routine is called each time a property value has been set.
//This will //cause an event to notify WPF via data-binding that a change has occurred.
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private ObservableCollection<T> collection;
public ObservableCollection<T> Collection
{
get
{
if (collection == null)
{
Get();
}
return collection;
}
set { collection = value; OnPropertyChanged("Collection"); }
}
private ICommand getCommand;
private ICommand saveCommand;
private ICommand removeCommand;
public ICommand GetCommand
{
get
{
return getCommand ?? (getCommand = new RelayCommand(Get, CanGet));
}
}
protected virtual bool CanGet()
{
return true;
}
protected virtual void Get()
{
//return true;
}
//public ICommand SaveCommand
//{
// get
// {
// return saveCommand ?? (saveCommand = new RelayCommand(param => Save()));
// }
//}
protected virtual bool CanSave()
{
return true;
}
//public ICommand DeleteCommand
//{
// get
// {
// return removeCommand ?? (removeCommand = new RelayCommand(param => Delete()));
// }
//}
protected virtual bool CanDelete()
{
return true;
}
}
现在您的视图将是这样的。
<Page.Resources>
<vm:ProductViewModel x:Key="product"/>
<vm:SupplierViewModel x:Key="supplier"/>
<DataTemplate x:Key="SupplierDataTemplate">
<TextBlock Text="{Binding supplier}"/>
</DataTemplate>
</Page.Resources>
<Grid>
<StackPanel>
<Grid DataContext="{Binding Source={StaticResource product}}" x:Name="ProductGrid">
<StackPanel Grid.ColumnSpan="2" Margin="0,0,58,0">
<Button x:Name="BtnDelete"
Content="Delete"
Command="{Binding DeleteCommand}"/>
<Button x:Name="BtnAdd"
Content="Save"
Command="{Binding SaveCommand}"/>
<DataGrid x:Name="dataGrid" Margin="5" ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="id" Binding="{Binding idproduct, UpdateSourceTrigger=PropertyChanged}" Visibility="Hidden"/>
<DataGridTextColumn Header="Ref FTHK" Binding="{Binding ref, UpdateSourceTrigger=PropertyChanged}" />
<DataGridComboBoxColumn Header="Supplier" ItemsSource="{Binding Collection, Source={StaticResource supplier}}"
DisplayMemberPath="supplier"
SelectedValueBinding="{Binding supplier}"/>
<DataGridTextColumn Header="Ref Supplier" Binding="{Binding refsup, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Description" Binding="{Binding description, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="MOQ" Binding="{Binding MOQ, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Unit" Binding="{Binding unit, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Prix/MOQ" Binding="{Binding priceMOQ, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding GetCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>-->
</DataGrid>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
希望对您有所帮助
我想在我的数据网格 "Product" 中添加一个包含供应商列表的 ComboBox 列。但我所做的一切都不起作用。绑定此列的好方法是什么?
模特们:
public partial class foodSupplier
{
public foodSupplier()
{
this.products = new HashSet<product>();
}
public int idfoodSupplier { get; set; }
public string supplier { get; set; }
public virtual ICollection<product> products { get; set; }
}
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; }
}
这是我的命令库(ViewModel):
public class CommandBase<T> :INotifyPropertyChanged
{
#region "INotifyPropertyChanged members"
public event PropertyChangedEventHandler PropertyChanged;
//This routine is called each time a property value has been set.
//This will //cause an event to notify WPF via data-binding that a change has occurred.
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private ObservableCollection<T> collection;
public ObservableCollection<T> Collection
{
get
{
if (collection == null)
{
collection = new ObservableCollection<T>();
}
return collection;
}
set { collection = value; OnPropertyChanged("Collection");}
}
private ICommand getCommand;
private ICommand saveCommand;
private ICommand removeCommand;
public ICommand GetCommand
{
get
{
return getCommand ?? (getCommand = new RelayCommand(param => Get(),param=>CanGet()));
}
}
protected virtual bool CanGet()
{
return true;
}
public ICommand SaveCommand
{
get
{
return saveCommand ?? (saveCommand = new RelayCommand(param => Save()));
}
}
protected virtual bool CanSave()
{
return true;
}
public ICommand DeleteCommand
{
get
{
return removeCommand ?? (removeCommand = new RelayCommand(param=>Delete()));
}
}
protected virtual bool CanDelete()
{
return true;
}
}
这里是 ProductViewModel:
public class ProductViewModel : CommandBase<product>
{
public Context ctx = new Context();
protected override void Get()
{
ctx.products.ToList().ForEach(supplier => ctx.products.Local.Add(supplier));
Collection = ctx.products.Local;
}
protected override bool CanGet()
{
return true;
}
protected override void Save()
{
foreach (product item in Collection)
{
if (ctx.Entry(item).State == System.Data.Entity.EntityState.Added)
{
ctx.products.Add(item);
}
}
ctx.SaveChanges();
}
}
}
这里是 SupplierViewModel:
public class SupplierViewModel : CommandBase<foodSupplier>
{
public Context ctx = new Context();
protected override void Get()
{
ctx.foodSuppliers.ToList().ForEach(supplier => ctx.foodSuppliers.Local.Add(supplier));
Collection = ctx.foodSuppliers.Local;
}
protected override bool CanGet()
{
return true;
}
protected override void Save()
{
foreach (foodSupplier item in Collection)
{
if (ctx.Entry(item).State == System.Data.Entity.EntityState.Added)
{
ctx.foodSuppliers.Add(item);
}
}
ctx.SaveChanges();
}
}
这里的观点:
<Page.Resources>
<vm:ProductViewModel x:Key="product"/>
<vm:SupplierViewModel x:Key="supplier"/>
</Page.Resources>
<Grid DataContext="{Binding Source={StaticResource product}}">
<StackPanel Grid.ColumnSpan="2" Margin="0,0,58,0">
<Button x:Name="BtnDelete"
Content="Delete"
Command="{Binding DeleteCommand}"/>
<Button x:Name="BtnAdd"
Content="Save"
Command="{Binding SaveCommand}"/>
<DataGrid x:Name="dataGrid" Margin="5" ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="id" Binding="{Binding idproduct, UpdateSourceTrigger=PropertyChanged}" Visibility="Hidden"/>
<DataGridTextColumn Header="Ref FTHK" Binding="{Binding ref, UpdateSourceTrigger=PropertyChanged}" />
<DataGridComboBoxColumn Header="Supplier" ItemsSource="{Binding Collection, Source={StaticResource supplier}}????" DisplayMemberPath="supplier" SelectedValueBinding="{Binding ????}" SelectedValuePath="idSupplier"/>
<DataGridTextColumn Header="Ref Supplier" Binding="{Binding refsup, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Description" Binding="{Binding description, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="MOQ" Binding="{Binding MOQ, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Unit" Binding="{Binding unit, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Prix/MOQ" Binding="{Binding priceMOQ, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding GetCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
</StackPanel>
</Grid>
您必须像加载产品一样加载 SupplierCollection。我更喜欢随需应变的概念。类似于下面的代码
public class CommandBase<T> : INotifyPropertyChanged
{
#region "INotifyPropertyChanged members"
public event PropertyChangedEventHandler PropertyChanged;
//This routine is called each time a property value has been set.
//This will //cause an event to notify WPF via data-binding that a change has occurred.
protected void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
private ObservableCollection<T> collection;
public ObservableCollection<T> Collection
{
get
{
if (collection == null)
{
Get();
}
return collection;
}
set { collection = value; OnPropertyChanged("Collection"); }
}
private ICommand getCommand;
private ICommand saveCommand;
private ICommand removeCommand;
public ICommand GetCommand
{
get
{
return getCommand ?? (getCommand = new RelayCommand(Get, CanGet));
}
}
protected virtual bool CanGet()
{
return true;
}
protected virtual void Get()
{
//return true;
}
//public ICommand SaveCommand
//{
// get
// {
// return saveCommand ?? (saveCommand = new RelayCommand(param => Save()));
// }
//}
protected virtual bool CanSave()
{
return true;
}
//public ICommand DeleteCommand
//{
// get
// {
// return removeCommand ?? (removeCommand = new RelayCommand(param => Delete()));
// }
//}
protected virtual bool CanDelete()
{
return true;
}
}
现在您的视图将是这样的。
<Page.Resources>
<vm:ProductViewModel x:Key="product"/>
<vm:SupplierViewModel x:Key="supplier"/>
<DataTemplate x:Key="SupplierDataTemplate">
<TextBlock Text="{Binding supplier}"/>
</DataTemplate>
</Page.Resources>
<Grid>
<StackPanel>
<Grid DataContext="{Binding Source={StaticResource product}}" x:Name="ProductGrid">
<StackPanel Grid.ColumnSpan="2" Margin="0,0,58,0">
<Button x:Name="BtnDelete"
Content="Delete"
Command="{Binding DeleteCommand}"/>
<Button x:Name="BtnAdd"
Content="Save"
Command="{Binding SaveCommand}"/>
<DataGrid x:Name="dataGrid" Margin="5" ItemsSource="{Binding Collection}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="id" Binding="{Binding idproduct, UpdateSourceTrigger=PropertyChanged}" Visibility="Hidden"/>
<DataGridTextColumn Header="Ref FTHK" Binding="{Binding ref, UpdateSourceTrigger=PropertyChanged}" />
<DataGridComboBoxColumn Header="Supplier" ItemsSource="{Binding Collection, Source={StaticResource supplier}}"
DisplayMemberPath="supplier"
SelectedValueBinding="{Binding supplier}"/>
<DataGridTextColumn Header="Ref Supplier" Binding="{Binding refsup, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Description" Binding="{Binding description, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="MOQ" Binding="{Binding MOQ, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Unit" Binding="{Binding unit, UpdateSourceTrigger=PropertyChanged}"/>
<DataGridTextColumn Header="Prix/MOQ" Binding="{Binding priceMOQ, UpdateSourceTrigger=PropertyChanged}"/>
</DataGrid.Columns>
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding GetCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>-->
</DataGrid>
</StackPanel>
</Grid>
</StackPanel>
</Grid>
希望对您有所帮助