无论如何要设置“DataContext” ListView 列共享的行的?
这是我能想到的表达我的问题的最佳方式,以下是场景:我有一个绑定到对象集合的 ListView
。每个对象都有一个属性 UserID
,它只是 User
对象的引用 ID。在我的 ListView 中,我希望显示对象和用户的多个属性。为此,我创建了一个实现 MultiValueConverter 的类来充当用户对象的查找表。因此,我使用多重绑定,它将 UserID 和底层 ViewModel 公开的字典查找表传递给值转换器。
这一切都工作得很好,除了我希望有一种方法可以设置 DataContext
或 ListView
列共享的“行”的某些内容。通过这种方式,我可以更改值转换器以仅返回用户对象而不是用户对象的特定属性。然后我可以绑定到该 DataContext 的属性。我不想为我希望公开的每个用户属性创建一个新的值转换器。我能想到的唯一其他方法是将属性名称传递给值转换器并使用反射。
有什么想法吗?我意识到我梦想的这个 DataContext
是绑定到 ListView
的 ItemsSource
的数据对象的工作,但也许还有其他东西我也可以用。附加属性似乎解决了我遇到的每个 WPF 问题,所以我打赌解决方案必须使用 AttachedProperty
来创建这个“数据上下文”,
我确信有人会告诉我公开 User 对象从数据对象本身,而不是使用一些使用用户 ID 和查找表的向后方法,但是,我这样做是有原因的。谢谢。
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.Header>User</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock MinWidth="120">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource UserIDConverter}">
<Binding Path="UserID" />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" Path="DataContext.Users"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
转换器:
public class UserIDConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
int userId = (int)values[0];
IDictionary<int, PhoneUser> table = values[1] as IDictionary<int, PhoneUser>;
if (table.ContainsKey(userId))
{
PhoneUser user = table[userId];
return user.LastName;
//I'd like to just return user !!
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
That's the best way I could think of to phrase my question, here is the scenario: I have a ListView
bound to a collection of objects. Each of those objects has a property UserID
which is just a reference ID to a User
object. In my ListView
I wish to display multiple properties from both the object and the User
. To do this I have created a class that implements MultiValueConverter
to serve as a lookup table for the user objects. So I use a multibinding which passes the value converter the UserID
and a dictionary look up table which is exposed by the underlying ViewModel.
This all works fine and dandy except I am hoping there is a way I could set the DataContext
or something of the 'row' that the ListView
columns share. In this way I could change my value converter to just return a User object instead of specific properties of the user object. And then I could just bind to the properties of that DataContext
. I don't want to create a new value converter for each User property I wish to expose. The only other way I can think of to do this is by passing property names to value converter and using reflection.
Any ideas? I realize that this DataContext
I am dreaming of is the job of the dataobjects bound to the ListView
's ItemsSource
, but perhaps there is something else I could use too. Attached Properties seem to solve every WPF problem I have so I am betting the solution would have to do with using an AttachedProperty
to create this 'datacontext'
I'm sure someone will tell me to expose the User object from the dataobjects themselves instead of using some backwards method of using user ids and lookup table, BUT, I am doing this for a reason. thanks.
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.Header>User</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock MinWidth="120">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource UserIDConverter}">
<Binding Path="UserID" />
<Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=UserControl}" Path="DataContext.Users"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
The converter:
public class UserIDConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
int userId = (int)values[0];
IDictionary<int, PhoneUser> table = values[1] as IDictionary<int, PhoneUser>;
if (table.ContainsKey(userId))
{
PhoneUser user = table[userId];
return user.LastName;
//I'd like to just return user !!
}
return null;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因此,如果我理解正确的话,您希望转换器只返回整个
PhoneUser
对象,然后让每一列决定要获取PhoneUser
的哪个属性?如果您真的要坚持这种复杂的方法,我认为您的反射想法(将属性名称传递到转换器并使用反射返回值)将是最好的。
也就是说,我无法抗拒给出你不想听到的答案(即使它对你没有帮助,但可能对其他人有帮助)。这就是我真正建议您做的事情...
创建一个组合当前对象(假设它称为
Foo
)和PhoneUser<的类/代码>.
使用 LINQ 将这两个类组合在一起:
从
GridViewColumn
中删除所有绑定标记,然后放置如下内容:或
So, if I understand you correctly, you'd like your converter to just return an entire
PhoneUser
object, then have each column decide which property ofPhoneUser
to grab?If you're really going to insist on this convoluted method, I think your reflection idea (pass the property name into the converter and use reflection to return the value) would be best.
That said, I can't resist giving the answer you didn't want to hear (even if it doesn't help you, it might help someone else). Here's what I'd really recommend you do...
Create a class that combines your current object (say it's called
Foo
) and aPhoneUser
.Use LINQ to combine these two classes together:
Get rid of all that binding markup from your
GridViewColumn
, and just put something like this:or
如果您可以使用
PhoneUser
填充数据对象,而不仅仅是 ID,那么您可以这样做:类结构将如下所示:
如果它不适合您检索首次加载数据对象时的所有用户数据,您可以使用“延迟加载”策略,如下所示:
我相信您可以在不更改代码结构的情况下执行此操作。
It would be much easier if you could populate your data object with
PhoneUser
, instead of just the ID, then you could do:The class structure would look something like this:
If it does not suit you to retrieve all user data when the data object is first loaded, you could use a "Lazy Loading" strategy, like this:
I believe you could do this without any changes to the structure of your code.