绑定协方差集合WPF

时间:2014-08-26 12:26:24

标签: c# wpf listview binding covariance

我有:

public class BaseSong 
{    
    public string Artist
    {
        get; set;
    }
    public string Title
    {
        get; set;
    }

public class ExtendedSong : BaseSong
{
    public string Bitrate { get; set;}
    ...
}

public class CollectionSong<T> : ObservableCollection<T>  where T : BaseSong
{
    ...
}
public class Playlist
{
    CollectionSong _collectionSong;
    public CollectionSong<BaseSong> Collection
    { 
         get { return _collectionSong; }
         set {...}
    }
    public Playlist()
    {}
    ...
}

我可以这样

Playlist plist= new Playlist();
plist.Collection = new CollectionSong<BaseSong>();
plist.Collection.Add(new ExtendedSong(){...});

ListView lv = new ListView();
lv.ItemSource = plist.Collection;

但是,我怎么能说ListView关于show listViewItem为ExtendedSong而不是BaseSong?

P.S。集合只有BaseSong项目或只有ExtendedSong

private ListView CreateListView(PlaylistViewModel model)
        {
            System.Windows.Controls.ListView lv = new System.Windows.Controls.ListView();
            lv.SetBinding(ListView.ItemsSourceProperty, new Binding("Collection")
            {
                Source = model,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            });
            lv.SetBinding(ListView.ViewProperty, new Binding("ColumnConfig")
                {
                    Converter = new VkPlayer.Helpers.ConfigToDynamicGridViewConverter()
                });
            return lv;
        }
DataTemplate songLayout = new DataTemplate();
            songLayout.DataType = typeof(ExtendedSong);

            FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(TextBlock));
            spFactory.Name = "textBoxFactory";
            spFactory.SetBinding(TextBlock.TextProperty, new Binding("Bitrate"));
            songLayout.VisualTree = spFactory;
ColumnConfig = new ColumnConfig { Columns = new List<Column> { 
                new Column { Header = "Title", DataField = "FullName" }, 
                new Column { Header = "Bitrate", Template = songLayout}
                 }
            };

  public class ConfigToDynamicGridViewConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            var config = value as ColumnConfig;
            if (config != null)
            {
                var grdiView = new GridView();
                foreach (var column in config.Columns)
                {
                    var grwCol = new GridViewColumn { Header = column.Header };
                    if (column.DataField != null)
                    {
                        var binding = new System.Windows.Data.Binding(column.DataField);
                        if (column.Converter != null)
                            binding.Converter = column.Converter as System.Windows.Data.IValueConverter;
                        if (column.ConverterParameter != null)
                        {
                            binding.ConverterParameter = column.ConverterParameter;
                        }
                        grwCol.DisplayMemberBinding = binding;
                    }
                    else
                    {
                        grwCol.CellTemplate = column.Template;
                    }
                    grdiView.Columns.Add(grwCol);
                }
                return grdiView;
            }
            return System.Windows.Data.Binding.DoNothing;
        }

不工作,输出:  System.Windows.Data错误:40:BindingExpression路径错误:&#39; Bitrate&#39;在&#39; object&#39;上找不到的属性&#39;&#39; BaseSong&#39; (的HashCode = 23764897)&#39;

2 个答案:

答案 0 :(得分:3)

在WPF中,我们使用DataTemplate来定义我们的数据对象在UI中应该是什么样子。有关数据绑定的详细信息,请参阅MSDN上的Data Binding Overview页面。因此,我们只需为您的每种数据类型声明DataTemplate,并且每个DataTemplate的内容都可以访问该类型的属性。尝试这样的事情:

<DataTemplate DataType="{x:Type YourPrefix:BaseSong}">
    <TextBlock Text="{Binding Title}" />
</DataTemplate>
<DataTemplate DataType="{x:Type YourPrefix:ExtendedSong}">
    <TextBlock Text="{Binding Bitrate}" />
</DataTemplate>

...

<ListBox ItemsSource="{Binding CollectionSong" ... />

这就是你所要做的一切。

答案 1 :(得分:0)

public class CollectionSong<T> : ObservableCollection<T>  where T : BaseSong
{
   public CollectionSong<ExtendedSong> ToExSongs() {...}
}
public CollectionSong<BaseSong> CollectionEx
    { 
         get { return Collection.ToExSongs(); }
         set {...}
    }