Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何为显式实现的接口设置DisplayMemberPath?_C#_Wpf - Fatal编程技术网

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

C# 如何为显式实现的接口设置DisplayMemberPath?,c#,wpf,C#,Wpf,我的User类显式地实现了IUser接口。此类为内部,但接口为公共。在另一个程序集中,我获取IEnumerable数据,并尝试将其设置为WPF元素的数据源 我使用的DisplayMemberPath属性有问题 这是我的界面: public interface IUser { string Name { get; set; } string MiddleName { get; set; } string Surname { get; set; } } 这是我的用户课

我的
User
类显式地实现了
IUser
接口。此类为
内部
,但接口为
公共
。在另一个程序集中,我获取
IEnumerable
数据,并尝试将其设置为WPF元素的数据源

我使用的
DisplayMemberPath
属性有问题

这是我的界面:

public interface IUser {

    string Name { get; set; }

    string MiddleName { get; set; }

    string Surname { get; set; }
}
这是我的
用户
课程:

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);
IFactory factory=factory.Current;
IProjectDataProvider provider=factory.CreateProjectDataProvider()
;
//获取数据源
IEnumerable users=provider.GetProjectMainArchitects();
win窗口=新窗口();
ComboBox cbox=新ComboBox();
cbox.宽度=200;
cbox.高度=20;
cbox.HorizontalAlignment=HorizontalAlignment.Center;
cbox.VerticalAlignment=垂直对齐.中心;
win.Content=cbox;
绑定=新绑定();
bind.Source=用户;
cbox.SetBinding(ItemsControl.ItemsSourceProperty,bind);
//cbox.DisplayMemberPath=“Name”;
应用程序app=新应用程序();
应用程序运行(win);
结果是:

但是如果我取消注释
//cbox.DisplayMemberPath=“Name”代码行然后我得到这样的结果:


如何解决此问题?

就像我说的,您必须至少公开您的Name属性才能从另一个程序集访问它。也许此链接有助于您了解问题:

简短形式:您可以在另一个程序集中访问接口,但当显式类型位于另一个程序集和内部时,不能访问它的属性


因为绑定需要公共访问,所以无法看到名称。

问题不在于类的可见性,而在于明确实现了接口。从可见性的角度来看,显式实现相当于它是私有的(实际上它比私有的更糟糕,因为您只能通过显式转换从类本身内部调用它)

绑定只能看到公共成员,因此无法看到类的显式实现成员。(省略公共修饰符是一个提示!)

通常需要显式实现某些内容的唯一原因是名称冲突

请尝试以下操作以查看问题:

代码隐藏:

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>

设置
DisplayMemberPath
属性对于显式实现的属性不起作用

您应该使用显式绑定到显式实现的属性的
TextBlock
定义一个
ItemTemplate

这在XAML中很容易做到:

<ComboBox>
    <ComboBox.ItemTemplate>
        <DataTemplate xmlns:local="clr-namespace:WpfApplication1;assembly=WpfApplication1">
            <TextBlock Text="{Binding (local:IUser.Name)}" />
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

不要忘记将“WpfApplication1”替换为定义了
IUser
接口的名称空间和程序集的实际名称。

我想您已经尝试将用户类公开,不是吗?或者它与您的视图在同一个程序集中?
User
类将是
internal
,hi是。我的第二个代码示例位于其他程序集中。我这样做是为了让工作严格通过接口来执行。这就解释了为什么在第二个示例中看不到任何东西。因为另一个程序集无权访问您的用户类及其属性。我将
IEnumerable
作为数据源
IUser
实例可供使用,因为此接口声明为
public
。解决此问题的简单方法是将
Name
公开(
User
类在此情况下仍然可以是内部的)。所有对属性的访问都是通过反射完成的,所以在这种情况下,是否传递类或接口实例无关紧要。WPF将(基本上)执行GetType().GetProperty(“名称”)。同意您所说的一切,除非有其他原因需要显式实现。也许你想隐藏一个与你的类型不相关的成员,例如过时的。非常同意!您需要显式实现的唯一原因是名称冲突,但也有一些架构原因,您可能希望强制某人进行强制转换以调用。(目前情况相当冷淡,投票表决如何?)我隐藏了实现,以便于测试和替换实现。我尝试使用它:
cbox.ItemTemplate=XamlReader.Parse(“”)作为数据模板但它不起作用。“不起作用”是什么意思?您是否遇到异常或发生了什么?你的程序集真的被命名为“Core”吗?这意味着我得到了与我在第二个屏幕上显示的相同的无效结果。不,我也不例外。是的,它的名称是
Core.dll
。那么,在设置ItemTemplate属性时,您在组合框中看到了什么?出于测试目的,尝试将XAML中TextBlock的Text属性设置为静态字符串。如果没有看到此文本,则表示尚未应用ItemTemplate。请用完整回购更新您的问题。
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;