我的User
班级明确实施IUser
界面 。此类为internal
,但界面为public
。在我的其他程序集中,我得到IEnumerable<IUser>
数据,并尝试将其设置为我的WPF元素的数据源。
我遇到DisplayMemberPath
属性使用的问题。
这是我的界面:
public interface IUser {
string Name { get; set; }
string MiddleName { get; set; }
string Surname { get; set; }
}
这是我的User
课程:
internal class User : IUser {
public User(string name, string middleName, string surname) {
IUser user = (IUser)this;
user.Name = name;
user.MiddleName = middleName;
user.Surname = surname;
}
string name;
string IUser.Name {
get {
return name;
}
set {
if (IsValidName(value)) {
name = value?.Trim();
}
else {
throw new ArgumentException(nameof(IUser.Name));
}
}
}
private bool IsValidName(string value) {
if (string.IsNullOrEmpty(value)) {
return false;
}
string tmp = value.Trim();
if (tmp.All(n => char.IsLetter(n))) {
return true;
}
return false;
}
string middleName;
string IUser.MiddleName {
get {
return middleName;
}
set {
if (IsValidName(value)) {
middleName = value?.Trim();
}
else {
throw new ArgumentException(nameof(IUser.MiddleName));
}
}
}
string surname;
string IUser.Surname {
get {
return surname;
}
set {
if (IsValidName(value)) {
surname = value?.Trim();
}
else {
throw new ArgumentException(nameof(IUser.Surname));
}
}
}
}
这是IUser
使用的代码:
IFactory factory = Factory.Current;
IProjectDataProvider provider = factory.CreateProjectDataProvider()
;
// Get data sources
IEnumerable<IUser> users = provider.GetProjectMainArchitects();
Window win = new Window();
ComboBox cbox = new ComboBox();
cbox.Width = 200;
cbox.Height = 20;
cbox.HorizontalAlignment = HorizontalAlignment.Center;
cbox.VerticalAlignment = VerticalAlignment.Center;
win.Content = cbox;
Binding bind = new Binding();
bind.Source = users;
cbox.SetBinding(ItemsControl.ItemsSourceProperty, bind);
// cbox.DisplayMemberPath = "Name";
Application app = new Application();
app.Run(win);
结果如下:
但如果我取消注释// cbox.DisplayMemberPath = "Name";
代码行,那么我得到这样的结果:
我该如何解决这个问题?
答案 0 :(得分:1)
设置ps aux
属性不适用于显式实现的属性。
您应该定义一个DisplayMemberPath
,其ItemTemplate
明确绑定到显式实现的属性。
这在XAML中很容易做到:
TextBlock
如果您出于某种原因想以编程方式执行此操作,可以使用<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate xmlns:local="clr-namespace:WpfApplication1;assembly=WpfApplication1">
<TextBlock Text="{Binding (local:IUser.Name)}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
创建XamlReader.Parse
:
DataTemplate
不要忘记将“WpfApplication1”替换为命名空间的实际名称和定义cbox.SetBinding(ItemsControl.ItemsSourceProperty, bind);
cbox.ItemTemplate = System.Windows.Markup.XamlReader.Parse("<DataTemplate xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\" xmlns:local=\"clr-namespace:WpfApplication1;assembly=WpfApplication1\"><TextBlock Text=\"{Binding (local:IUser.Name)}\" /></DataTemplate>") as DataTemplate;
this.Content = cbox;
接口的程序集。
答案 1 :(得分:0)
就像我说的那样,你必须至少让你的Name属性公开才能从另一个程序集中访问它。也许这个链接可以帮助您理解问题:Access Modifiers (C# Programming Guide)
简短表单:您可以在另一个程序集中访问您的界面,但在另一个程序集和内部部署时,不能访问显式类型的属性。
由于您的绑定需要公开访问,因此无法看到名称。
答案 2 :(得分:0)
您遇到的问题不是类的可见性,而是您已明确实现接口的事实。从可见性的角度来看,显式实现等同于它是私有的(实际上它比那更糟,因为你只能通过显式转换从类本身内调用它)。
绑定只能看到公共成员,因此无法看到该类的明确实现的成员。 (遗漏公共修饰语是一个暗示!)
您通常需要明确实现某些内容的唯一原因是由于名称冲突。
试试看这个问题:
代码背后:
public interface IBlah
{
string ExplicitMember { get; set; }
string Member { get; set; }
}
public partial class MainWindow : IBlah
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
string IBlah.ExplicitMember { get; set; } = "Hidden";
public string Member { get; set; } = "Visible";
}
这在XAML中:
<Window
x:Class="ExplicitBind.MainWindow"
Title="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ExplicitBind"
Height="350"
Width="525"
mc:Ignorable="d">
<StackPanel>
<TextBox Text="{Binding ExplicitMember}" />
<TextBox Text="{Binding Member}" />
</StackPanel>
</Window>