C# 是否仍要设置ListView列共享的行的“DataContext”?
这是我能想到的表达我的问题的最好方式,下面是一个场景:我有一个绑定到对象集合的ListView。每个对象都有一个属性UserID,它只是用户对象的引用ID。在我的ListView中,我希望显示对象和用户的多个属性。为此,我创建了一个实现MultiValueConverter的类,作为用户对象的查找表。因此,我使用了一个多重绑定,它向值转换器传递UserID和一个字典查找表,该表由底层ViewModel公开 除了我希望有一种方法可以设置DataContext或ListView列共享的“行”的某些内容之外,所有这些都可以很好地工作。通过这种方式,我可以将我的值转换器更改为只返回一个用户对象,而不是用户对象的特定属性。然后我可以绑定到DataContext的属性。我不想为我想要公开的每个用户属性创建一个新的值转换器。我能想到的唯一其他方法是将属性名传递给值转换器并使用反射 有什么想法吗?我意识到我梦寐以求的这个DataContext是绑定到ListView的ItemsSource的dataobjects的工作,但也许我还可以使用其他东西。附加属性似乎解决了我遇到的每个WPF问题,所以我打赌解决方案必须使用AttachedProperty来创建这个“datacontext” 我相信有人会告诉我从数据对象本身公开用户对象,而不是使用一些向后的方法使用用户ID和查找表,但是,我这样做是有原因的。谢谢C# 是否仍要设置ListView列共享的行的“DataContext”?,c#,wpf,listview,datacontext,C#,Wpf,Listview,Datacontext,这是我能想到的表达我的问题的最好方式,下面是一个场景:我有一个绑定到对象集合的ListView。每个对象都有一个属性UserID,它只是用户对象的引用ID。在我的ListView中,我希望显示对象和用户的多个属性。为此,我创建了一个实现MultiValueConverter的类,作为用户对象的查找表。因此,我使用了一个多重绑定,它向值转换器传递UserID和一个字典查找表,该表由底层ViewModel公开 除了我希望有一种方法可以设置DataContext或ListView列共享的“行”的某些内
<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
}
如果您可以使用PhoneUser(而不仅仅是ID)填充数据对象,那么您可以执行以下操作:
<DataTemplate>
<StackPanel>
<TextBlock MinWidth="120" Text="{Binding Path="User.FirstName}">
</TextBlock>
<TextBlock MinWidth="120" Text="{Binding Path="User.LastName}">
</TextBlock>
</StackPanel>
</DataTemplate>
如果不适合在首次加载数据对象时检索所有用户数据,则可以使用延迟加载策略,如下所示:
public class myDataObject //The data object you already have.
{
public string value1;
public string value2;
public PhoneUser User; //currently you have "UserID" here.
}
public class PhoneUser
{
public string FirstName;
public string LastName;
}
public class myDataObject //The data object you already have.
{
public string UserID;
public string value2;
private PhoneUser _User;
public PhoneUser User
{
get
{
if(_User==null)
_User = getUserFromDatabase(UserID);
return _User;
}
}
}
<TextBlock MinWidth="120" Text={Binding User.LastName} />
我相信您可以在不更改代码结构的情况下执行此操作。因此,如果我理解正确,您希望转换器只返回整个PhoneUser对象,然后让每列决定要获取PhoneUser的哪个属性 如果您真的要坚持使用这种复杂的方法,我认为您的反射想法最好将属性名传递到转换器中,并使用反射返回值 也就是说,我忍不住给出你不想听的答案,即使它对你没有帮助,也可能对其他人有帮助。这是我真正建议你做的 创建一个类,将当前对象(比如称为Foo)和一个PhoneUser)组合在一起 使用LINQ将这两个类组合在一起:
var FooPhoneUsers =
from
f in Foos
join
pu in PhoneUsers on f.UserId equals pu.Id
select
new FooPhoneUser { Foo = f, User = pu };
摆脱GridViewColumn中的所有绑定标记,只需放置如下内容:
public class myDataObject //The data object you already have.
{
public string value1;
public string value2;
public PhoneUser User; //currently you have "UserID" here.
}
public class PhoneUser
{
public string FirstName;
public string LastName;
}
public class myDataObject //The data object you already have.
{
public string UserID;
public string value2;
private PhoneUser _User;
public PhoneUser User
{
get
{
if(_User==null)
_User = getUserFromDatabase(UserID);
return _User;
}
}
}
<TextBlock MinWidth="120" Text={Binding User.LastName} />
或
谢谢,但正如问题中所述,我不想在数据对象类中使用对用户对象实例的引用。谢谢你这么想对不起,我错过了。你能详细说明你不想这样做的原因吗?如果我知道你的要求是基于什么,我可能会更好地给你一个好答案。我认为必须有一个比你正在尝试的更好的策略。“更好的策略”,我相信你是对的。我只是要修改我的其他层,这样我就可以在我的数据对象中使用一个用户对象。我想我只是被困在试图使这项工作,而不是将项目作为一个整体来考虑。@J-我已经修改了我的答案,加入了更多关于延迟加载的细节-这项工作的性能和有效性应该与您的问题所建议的相同。重构您的代码是一个好主意,但这可能会让您摆脱麻烦:在这一点上,我认为我的非UI层只是构思不周,所以我将对它们进行返工,以便在我的数据对象中使用用户对象引用。