【问题标题】:ListBox showing "Namespace.Accounts" instead of actual text [duplicate]ListBox 显示“Namespace.Accounts”而不是实际文本 [重复]
【发布时间】:2012-01-13 15:18:29
【问题描述】:

可能重复:
WPF ListBox - Display properties of the ItemSource

我正在尝试实现一个解决方案,该解决方案将在通过文本框和添加按钮添加项目后在列表框中显示项目......作为 WPF 的新手,我几乎已经弄清楚了(经过一周的敲打我的头靠在桌子上……哈哈)

问题是列表框填充的是“WinBudget.Accounts”,而不是输入到列表框中的实际项目。

请帮忙。

型号

// the model is the basic design of an object containing properties
// and methods of that object. This is an account object.

public class Account : INotifyPropertyChanged
{
    private string m_AccountName;

    public event PropertyChangedEventHandler PropertyChanged;

    public string AccountName
    {
       get { return m_AccountName;}
       set 
         { 
            m_AccountName = value;
            OnPropertyChanged("AccountName");
         }
    }

    protected void OnPropertyChanged(string name)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
          handler(this, new PropertyChangedEventArgs(name));
      }
    }
}

列表框 XAML

 <ListBox Name="MyAccounts" />

代码隐藏

// create a collection of accounts, then whenever the button is clicked,
//create a new account object and add to the collection.

public partial class Window1 : Window
{
    private ObservableCollection<Account> AccountList = new ObservableCollection<Account>();

    public Window1()
    {
        InitializeComponent();
        AccountList.Add(new Account{ AccountName = "My Account" });
        this.MyAccounts.ItemsSource = AccountList;
    }
     private void okBtn_Click(object sender, RoutedEventArgs e)
    {
       AccountList.Add(new Account{ AccountName = accountaddTextBox.Text});
    }
}

【问题讨论】:

  • @lance,引用了该线程。 DisplayMemberPath = "AccountName" 工作...非常感谢!!

标签: c# wpf


【解决方案1】:

WPF 的 UI 可以包含任何类型的对象,甚至是 Account 这样的类。如果 WPF 在 UI 中遇到它不理解的对象,它将使用包含该对象的 .ToString()TextBlock 来呈现它。

在您的情况下,ListBox.Item 是一个Account 对象,因此它使用Account.ToString() 呈现,它返回类名。

有很多不同的方法来处理这个问题。我的首选方法通常是使用DataTemplate。这将创建一个应用程序范围的模板,告诉 WPF 如何绘制特定类型的对象。

<Window.Resources>
    <DataTemplate TargetType="{x:Type local:Account}">
        <TextBlock Text="{Binding AccountName}" />
    </DataTemplate>
</Window.Resources>

另一种方法是覆盖ListBox.ItemTemplate 以指定ItemTemplate 用于您的ListBox。如果我想指定仅用于此ListBox 的模板,我通常会使用它

<ListBox Name="MyAccounts">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding AccountName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

如果您的模板很简单,例如所示的模板,您还可以设置 ListBox 的DisplayMemberPath,使默认模板看起来像上面所示的模板,绑定指向您在DisplayMemberPath 中输入的任何内容

<ListBox Name="MyAccounts" DisplayMemberPath="AccountName" />

当然,您也可以覆盖 Account 对象的 ToString() 方法以返回 AccountName 而不是默认的 ClassName,但我不建议在这种情况下使用它。

【讨论】:

    【解决方案2】:

    默认情况下,ListBox 的项目模板显示是为对象调用ToString() 的结果。所以你必须要么覆盖Account.ToString(),要么提供一个不同的模板。

    【讨论】:

    • 我更喜欢使用 ToString() 来显示诊断信息,而不是 UI 需求。
    【解决方案3】:

    最好绑定到Account::AccountName 属性,但如果你不知道或由于任何原因不能,快速而肮脏的解决方案可能是

    公共类帐户:INotifyPropertyChanged { 私有字符串 m_AccountName;

    public event PropertyChangedEventHandler PropertyChanged;
    
    public string AccountName
    {
       get { return m_AccountName;}
       set 
         { 
            m_AccountName = value;
            OnPropertyChanged("AccountName");
         }
    }
    
    protected void OnPropertyChanged(string name)
    {
      PropertyChangedEventHandler handler = PropertyChanged;
      if (handler != null)
      {
          handler(this, new PropertyChangedEventArgs(name));
      }
    }
    
    
    
    
       //NEW
       public override string ToString()
       {
           return AccountName;
       }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2012-02-09
      • 1970-01-01
      • 2013-01-27
      • 2021-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多