C# 使用MVVM以1:1将WPF中的DataGrid绑定到子导航属性(EF)
使用MVVM以1:1将WPF中的DataGrid绑定到子导航属性(EF) 全部, 使用.NET4和EF4.4(数据库优先) 我有一个ViewModel,其中包含对EntityCollection“Entity1”的引用 此实体与Entity2的关系为1:1 我的问题是,虽然我可以绑定到具有1:many或many:many关系的其他实体,但绑定到Entity1.Entity2时似乎有问题。我猜这是因为Entity2不是一个集合,所以WPF不太确定如何处理它 因此,除了向我的Entity1类(只包含一个Entity2实例,为1:1关系)添加ObservableCollection并绑定到该类之外,我想知道是否有更好的方法来实现我的目标,即在数据网格中显示Entity1.Entity2(无需重新设计my DB或创建最终只包含1个对象的不必要集合) 我已经尝试将Entity1.Entity2放在CollectionViewSource中,但这似乎没有任何帮助C# 使用MVVM以1:1将WPF中的DataGrid绑定到子导航属性(EF),c#,entity-framework,wpfdatagrid,one-to-one,C#,Entity Framework,Wpfdatagrid,One To One,使用MVVM以1:1将WPF中的DataGrid绑定到子导航属性(EF) 全部, 使用.NET4和EF4.4(数据库优先) 我有一个ViewModel,其中包含对EntityCollection“Entity1”的引用 此实体与Entity2的关系为1:1 我的问题是,虽然我可以绑定到具有1:many或many:many关系的其他实体,但绑定到Entity1.Entity2时似乎有问题。我猜这是因为Entity2不是一个集合,所以WPF不太确定如何处理它 因此,除了向我的Entity1类(只包含
谢谢。为什么要对单个实体使用datagrid?我绝对不会在模型中使用ObservableCollection属性来涵盖这一点 如果要显示所有entity1的所有entity2,可以将datagrid的ItemsSource绑定到entity1的集合,并深入到entity2的属性 另一个选项是构建一个自定义表单来表示entity2数据 尝试1 您完全可以从Entity1钻取Entity2中的属性。 试试这个:
//In your application layer
public class RecordsViewModel
{
public ObservableCollection<Record> Records {get;set;}
}
//In your domain layer
public class Record
{
//Properties from Entity1
//Properties from Entity2
}
//In your Data Access Layer
public class Repository
{
public IEnumerable<Record> GetRecords()
{
return db.Entity1.Include("Entity2")
.Select(e =>
new Record()
{
//object initialization
});
}
public void Update(IEnumerable<Record> records)
{
var recordIds = records.Select(r => r.Id);
var entities = db.Entity1.Include("Entity2").Where(e => recordIds.Contains(e.Id));
foreach(var record in records)
{
var entity = entities.SingleOrDefault(e => e.Id == record.Id);
if (entity == null)
{
entity = new Entity1();
db.Entity1.Add(entity);
}
//update properties on Entity1
//check if Entity2 should exist
//If so, create/update entity2
//If not, decide if you should delete entity2 or simply set Entity1.Entity2 to null
}
}
}
//在应用程序层中
公共类记录viewmodel
{
公共可观察收集记录{get;set;}
}
//在您的域层中
公开课记录
{
//来自Entity1的属性
//来自Entity2的属性
}
//在数据访问层中
公共类存储库
{
公共IEnumerable GetRecords()
{
返回db.Entity1.Include(“Entity2”)
.选择(e=>
新纪录()
{
//对象初始化
});
}
公共作废更新(IEnumerable记录)
{
var recordIds=records.Select(r=>r.Id);
var entities=db.Entity1.Include(“Entity2”)。其中(e=>recordIds.Contains(e.Id));
foreach(记录中的var记录)
{
var entity=entities.SingleOrDefault(e=>e.Id==record.Id);
if(实体==null)
{
实体=新实体1();
db.Entity1.Add(实体);
}
//更新Entity1上的属性
//检查Entity2是否应该存在
//如果是,请创建/更新entity2
//如果不是,请决定是删除entity2还是将Entity1.entity2设置为null
}
}
}
尝试1:
在创建实体类的T4模板中,将NavigationProperty更改为:
public string NavigationProperty(NavigationProperty navigationProperty)
{
var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
return string.Format(
CultureInfo.InvariantCulture,
"{0}\n\n {1} {2} {3}\n {{\n {4}get\n {{\n return _{3}; \n }}\n {5} set\n {{\n _{3}=value; OnSet{3}();\n }}\n }}\n\n {6}",
string.Format(CultureInfo.InvariantCulture, "{0} _{1};",_typeMapper.GetTypeName(navigationProperty.TypeUsage), _code.Escape(navigationProperty)),
AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
_code.Escape(navigationProperty),
_code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
string.Format(CultureInfo.InvariantCulture, "partial void OnSet{0}();", _code.Escape(navigationProperty)));
}
对于IValueConverter(为了避免在1:1关系中添加过多记录)
公共类CanadValueConverter:IValueConverter
{
私有类型;;
私有数据网格;
公共无效设置值(数据网格dg,T型)
{
_T=T;
_dg=dg;
}
公共对象转换(对象值、类型targetType、对象参数、CultureInfo区域性)
{
System.Collections.IEnumerable dgIS=值为System.Collections.IEnumerable;
如果(_dg!=null&&dgIS==_dg.ItemsSource)
{
如果(_dg.Items.Count>0)
return _dg.Items.Count我有理由对单个实体使用DataGrid。现在,我的问题是,如果我在ItemsSource中引用Entity1,并对ItemsSource中的每一列使用Entity2.Property,这会对Entity1.Entity2为null有任何影响吗?在我看来,我必须检查Entity1.Entity2!=null,然后分配Entity2在我可以编辑之前,但问题是我希望Entity1.Entity2在大多数情况下都是空的,修改T4模板(我已经做过)似乎更容易(尽管有点讨厌)并使ObservableCollection与Entity2I am保持同步。我希望能够允许最终用户在不单击任何按钮的情况下添加行(DataGrid.AllowUserToAddress=True)如果可能的话。但是,我有一个IValueConverter,它可以防止最终用户添加太多行。更重要的是,我倾向于将我的对象放在集合中并绑定到集合。因此,用户使用的多个Entity1可能有也可能没有Entity2?正确。Entity1:Entity2是1:0或1:1关系。这不是我的ViewModel包含对Entity1(和Entity1.Entity2)的引用所做的吗?看起来像
Partial Class Entity1:EntityBase
{
public SpecificObservableCollection<Entity2> Entity2_Observable
{
get;
set;
}
partial void OnSetEntity2()
{
Misc_Observable.Add(Entity2);
}
public class SpecificObservableCollection<T> : ObservableCollection<T>
{
public Action<T> SetValue { get; set; }
protected override void InsertItem(int index, T item)
{
if (item != null)
{
base.InsertItem(index, item);
}
}
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if (this.Count>0)
SetValue(this[0]);
}
}
protected override void DoStuffOnAdd()
{
Entity2_Observable = new SpecificObservableCollection<Entity2>();
Entity2_Observable.SetValue = a => _Entity2 = a;
}
}
public abstract class EntityBase
{
EntityBase()
{
DoStuffOnAdd();
}
protected virtual void DoStuffOnAdd() { }
}
public class CanAddValueConverter : IValueConverter
{
private Type _T;
private DataGrid _dg;
public void SetValues(DataGrid dg, Type T)
{
_T = T;
_dg = dg;
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
System.Collections.IEnumerable dgIS = value as System.Collections.IEnumerable;
if (_dg != null && dgIS == _dg.ItemsSource)
{
if (_dg.Items.Count > 0)
return _dg.Items.Count <= System.Convert.ToInt32(parameter) && _dg.Items[_dg.Items.Count - 1].GetType() != _T;
else
return true;
}
else
return false;
}
}