C# 如何在ObservableCollection上调用String.Joing';s作为列表的绑定属性(到列表视图)<;字符串>;

C# 如何在ObservableCollection上调用String.Joing';s作为列表的绑定属性(到列表视图)<;字符串>;,c#,wpf,xaml,data-binding,observablecollection,C#,Wpf,Xaml,Data Binding,Observablecollection,我有一个简单的可观察集合,它有两个公共属性,int-ID和List-Targets。隐藏的代码如下所示(删除不必要和不相关代码的简化代码): 公共类MyClass { 公共收集工作; 公共类 { 私有int-id; 私人名单目标; 公共整数ID { 获取{return id;} 设置{id=value;} } 公开列出目标 { 获取{返回目标;} 设置{targets=value;} } 公共类(int\u id,List\u目标) { id=_id; 目标=_目标; } } 公共MyClass

我有一个简单的可观察集合,它有两个公共属性,int-ID和List-Targets。隐藏的代码如下所示(删除不必要和不相关代码的简化代码):

公共类MyClass
{
公共收集工作;
公共类
{
私有int-id;
私人名单目标;
公共整数ID
{
获取{return id;}
设置{id=value;}
}
公开列出目标
{
获取{返回目标;}
设置{targets=value;}
}
公共类(int\u id,List\u目标)
{
id=_id;
目标=_目标;
}
}
公共MyClass()
{
初始化组件();
jobs=新的ObservableCollection();
myListView.ItemsSource=jobs;//作业是从窗口中的a加载程序填充的
}
}
xaml中的ListView和绑定如下所示:

  <ListView Name="MyListView" ItemsSource="{Binding Path=jobs, RelativeSource={RelativeSource AncestorType=Window},
            Mode=OneWay}" Width="480" Height="155" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,35,10,0" >
     <ListView.ContextMenu>
        <ContextMenu Name="contextMenuJobRemove">
           <ContextMenu.BitmapEffect>
              <OuterGlowBitmapEffect />
           </ContextMenu.BitmapEffect>
           <MenuItem Header="Remove" Click="contextMenuJobRemove_Click" CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=Parent}"/>
        </ContextMenu>
     </ListView.ContextMenu>
     <ListView.View>
        <GridView AllowsColumnReorder="True" ColumnHeaderToolTip="Broadcast call targets">
           <GridViewColumn DisplayMemberBinding="{Binding Path=ID}"   Header="ID"      Width="50" />
           <GridViewColumn DisplayMemberBinding="{Binding Path=Targets}" Header="Targets" Width="100" />
        </GridView>
     </ListView.View>
  </ListView>

因此,当ListView显示时,目标列正确地显示“(Collection)”。理想情况下,我希望此列显示类似于
String.Join(“,”,Targets.ToArray())
。如何做到这一点,我是在xaml中还是在代码隐藏中做到这一点?

一种方法是在绑定中使用a


但是,只有在更改属性(而不是集合内容)后,才会更新。因此,最好在对象中公开一个显示字符串属性,并在列表更改时发出该属性的更改通知。如果集合一开始没有更改,那么这些通知显然是不必要的。

您可以创建一个简单的值转换器:

public class ListConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          CultureInfo culture)
    {
        var enumerable = value as IEnumerable;
        if (enumerable == null)
            return string.Empty;
        return String.Join(", ", enumerable.ToArray());
    }

    public object ConvertBack(object value, Type targetType, object parameter,
                              CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
[ValueConversion(typeof(IEnumerable<string>), typeof(string))]
public class MyArrayToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        return String.Join (",", ( (IEnumerable<string>)value ).ToArray() );
    }

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

<Window
    ...
    xmlns:my="clr-namespace:XXXXXXXXXXXXXXXXXXXXXCSharpNamespace"
    ...>
    <Window.Resources>
        <my:MyArrayToStringConverter x:Key="myconverter" />
    </Window.Resources>
    ...
    "{Binding ... Converter={StaticResource myconverter}}"
</Window>
使用值转换器:

public class ListConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          CultureInfo culture)
    {
        var enumerable = value as IEnumerable;
        if (enumerable == null)
            return string.Empty;
        return String.Join(", ", enumerable.ToArray());
    }

    public object ConvertBack(object value, Type targetType, object parameter,
                              CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
[ValueConversion(typeof(IEnumerable<string>), typeof(string))]
public class MyArrayToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        return String.Join (",", ( (IEnumerable<string>)value ).ToArray() );
    }

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

<Window
    ...
    xmlns:my="clr-namespace:XXXXXXXXXXXXXXXXXXXXXCSharpNamespace"
    ...>
    <Window.Resources>
        <my:MyArrayToStringConverter x:Key="myconverter" />
    </Window.Resources>
    ...
    "{Binding ... Converter={StaticResource myconverter}}"
</Window>
[ValueConversion(typeof(IEnumerable)、typeof(string))]
公共类MyArrayToStringConverter:IValueConverter
{
公共对象转换(对象值,类型targetType,
对象参数,CultureInfo(区域性)
{
返回字符串.Join(“,”,((IEnumerable)value.ToArray());
}
公共对象转换回(对象值,类型targetType,
对象参数,CultureInfo(区域性)
{
抛出新的NotImplementedException();
}
}
...
“{Binding…Converter={StaticResource myconverter}”

谢谢。这绝对是做到这一点的方法。@kmark2:关于类设计的说明,如果不应该更改
目标
列表,我将使用只读数据类型,删除属性设置器,并创建字段。非常方便,你知道。@H.B:不知道它也接受对象:-),即使没有,我可能会选择
String.Join(“,”,values.Select(o=>o.ToString))
来避免重复的字符串连接,谁知道列表有多大。