【问题标题】:Unable to get DisplayMemberPath to show bound object data in listbox无法获取 DisplayMemberPath 以在列表框中显示绑定的对象数据
【发布时间】:2012-10-07 01:47:16
【问题描述】:

长话短说,我的应用程序的一部分包含一系列绑定到 Xaml 中的对象实例的列表框。使用IValueConverter,我能够从主对象中检索<Part> 对象列表并显示检索到的对象的.ToString() 形式。但是,我想做的是显示对象的 Name 属性。我将DisplayMemberPath 设置为Name,但结果仅将listboxitem 置空。我已经在下面发布了代码的相关部分:

XAML:

<Window.Resources>
    <local:LocationtoEquipmentCOnverter x:Key="locationEquipmentFiller" />
</Window.Resources>
<Window.DataContext>
    <local:MegaWdiget/>
</Window.DataContext>
<ListBox x:Name="listboxFront" HorizontalAlignment="Left" Margin="180,45,0,0" VerticalAlignment="Top" Width="82" Opacity="0.5" ItemsSource="{Binding ConverterParameter=Front, Converter={StaticResource locationEquipmentFiller}, Mode=OneWay}" DisplayMemberPath="Name"/>

值转换器:

public class LocationtoEquipmentCOnverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        MegaWidget MWidget = (MegaWidget)value;
        Location loc = MWidget.Locations[(string)parameter];
        return loc.Contents;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

MegaWidget 对象包含以下内容:

[XmlElement]
public Dictionary<string, Location> Locations { get; set; }

位置对象包含一个列表,其中包含我需要查询其名称的实际对象:

 public List<Part> Contents;

找到解决方案

按照 Mate 推荐的故障排除路线继续进行后,我发现传递的对象是 Part 对象而不是 ListBoxItems。这导致ListBox 被实际对象而不是ListBoxItems 填充。通过更改 ValueConverter 以传递 ListBoxItems 的 List 并将内容标记设置为我需要的内容,ListBoxes 可以正确填充。我在下面的问题区域中列出了解决方案:

【问题讨论】:

  • 如果调试LocationtoEquipmentCONverter方法,参数和答案是否正确? ConverterParameter=Front 可以转换成字符串吗?
  • 它确实返回了一个列表(在这种情况下是单个对象),其中包含所有需要的属性。如果我不添加 displaymemberpath,该对象甚至会显示在列表框中,但会显示继承 (system.MWidget.Part) 而不是公共字符串 Name 属性。

标签: c# wpf data-binding listboxitem ivalueconverter


【解决方案1】:

按照 Mate 建议的故障排除路线继续进行后,我发现传递的对象是 Part 对象而不是 ListBoxItems。这导致 ListBox 被实际对象而不是 ListBoxItems 填充。通过更改 ValueConverter 以传递 ListBoxItems 列表并将内容标记设置为我需要的内容,ListBoxes 可以正确填充。

新的ValueConverter:

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
    MegaWidget MWidget = (MegaWidget)value;
    Location loc = MWidget.Locations[(string)parameter];
    List<ListBoxItem> displayContent = new List<ListBoxItem>();

    foreach (Part item in loc.Contents)
    {
        ListBoxItem lbi = new ListBoxItem();
        lbi.Content = item.Name;
        displayContent.Add(lbi);
    }

    return displayContent;
}

【讨论】:

  • ChargerIIC 做得好! .如果您想提供符合“最佳实践”的解决方案,您还需要显示类声明部分。
【解决方案2】:

根据您的回复“如果我不添加 DisplayMemberPath,但显示继承 (system.MWidget.Part)”,我想属性 Name 为空。

要检查,请测试:

public class LocationtoEquipmentCOnverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,   System.Globalization.CultureInfo culture)
    {
        MegaWidget MWidget = (MegaWidget)value;
        Location loc = MWidget.Locations[(string)parameter];

        //Refers to Class "Content" used in loc.Contents collection. I do not know what the name that you have used
        foreach (Content item in loc.Contents)
        {
            item.Name += "***";
        }

        return loc.Contents;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

【讨论】:

  • 试过了,但 ListBoxItem 仍然是空的。我可以在调试期间进行钻取,看到完整的 List(包括 +string Name 字段)正在发送回 UI,但 ListBoxItem 保持空白。我还尝试将 DisplayMemberPath 设置为对象的其他属性:重量、插槽等,但仍然没有显示。
【解决方案3】:

这里是一个例子

  • 型号

    public class MegaWidget
    {
        public Dictionary<string, Location> Locations { get; set; }
    }
    
    public class Location
    {
        public List<Part> Contents { get; set; }
    }
    
    public class Part
    {
        public int Id { get; set; }
        public string PartName { get; set; }
    }
    
  • 转换器

    public class LocationEquipmentConverter : IValueConverter
    {
        public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
        {
            MegaWidget widget = value as MegaWidget;
            string location = (string) parameter;
            return widget?.Locations[ location ]?.Contents;
        }
    
        public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
        {
            throw new NotImplementedException( );
        }
    }
    
  • 视图模型

    public class FooViewModel : ViewModelBase
    {
        public FooViewModel()
        {
            Widget = new MegaWidget
            {
                Locations = new Dictionary<string, Location>
                {
                    [ "Front" ] = new Location
                    {
                        Contents = new List<Part>
                        {
                            new Part { Id = 1, PartName = "Part 01" },
                            new Part { Id = 2, PartName = "Part 02" },
                            new Part { Id = 3, PartName = "Part 03" },
                        }
                    },
                    [ "Back" ] = new Location
                    {
                        Contents = new List<Part>
                        {
                            new Part { Id = 11, PartName = "Part 11" },
                            new Part { Id = 12, PartName = "Part 12" },
                            new Part { Id = 13, PartName = "Part 13" },
                        }
                    },
                }
            };
        }
    
        public MegaWidget Widget { get; }
    
        #region Property FrontPart
        private Part _frontPart;
    
        public Part FrontPart
        {
            get { return _frontPart; }
            set { SetProperty( ref _frontPart, value ); }
        }
        #endregion
    
        #region Property BackPart
        private Part _backPart;
    
        public Part BackPart
        {
            get { return _backPart; }
            set { SetProperty( ref _backPart, value ); }
        }
        #endregion
    }
    
  • 查看

    <Window x:Class="WPG.WpfApp.FooView"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:ViewModel="clr-namespace:WPG.WpfApp.ViewModel"
            xmlns:local="clr-namespace:WPG.WpfApp"
            mc:Ignorable="d"
            Title="FooView" Height="300" Width="300">
        <Window.Resources>
            <ViewModel:LocationEquipmentConverter x:Key="LocationEquipmentConverter"/>
        </Window.Resources>
        <Window.DataContext>
            <ViewModel:FooViewModel/>
        </Window.DataContext>
        <Grid>
            <StackPanel>
                <ListBox ItemsSource="{Binding Widget, ConverterParameter=Front, Converter={StaticResource LocationEquipmentConverter}, Mode=OneWay}"
                         SelectedItem="{Binding Path=FrontPart}"
                         DisplayMemberPath="PartName"/>
                <ListBox ItemsSource="{Binding Widget, ConverterParameter=Back, Converter={StaticResource LocationEquipmentConverter}, Mode=OneWay}"
                         SelectedItem="{Binding Path=BackPart}"
                         DisplayMemberPath="PartName"/>
            </StackPanel>
        </Grid>
    </Window>
    
  • 截图

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多