如何为显式实现的接口设置DisplayMemberPath?

时间:2017-03-17 10:04:25

标签: c# wpf

我的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);

结果如下:

enter image description here

但如果我取消注释// cbox.DisplayMemberPath = "Name";代码行,那么我得到这样的结果:

enter image description here

我该如何解决这个问题?

3 个答案:

答案 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>